C# is probably my recommended language for anyone looking to get started with functional programming and event handling.
Its familiar Java/C like syntax, classic use of OOP, enterprise vibes will mean it'll be very familiar and easy for most to pick up. And as you go deeper, it'll introduce you to anonymous delegates, lambdas, true generics, higher order functions, true closures, list comprehensions, anonymous types, type inference, lazy evaluation and even a sprinkle of monads.
With the language extensions, you can get even further.
This is a great way to start learning about FP concepts without even knowing it and it'll make your switch to a more thorough FP language much easier, such as MLs, Lisps, Erlangs, and most proof languages.
I think mixed-paradigm languages make it harder to get started with functional programming, since they provide a crutch to other paradigms, which people tend to fall back on. I'd recommend Scheme, or maybe Elm (if you're doing web programming), as good starting points to learn FP, since both languages are relatively simple to learn and won't let you implement OOP, for instance.
I got started with functional programming with F#. I agree that there were times when I used its hybrid nature as a crutch, but I think there's a value in using a hybrid language if your goal is to learn. F# let me write out code in an imperative style that did what I wanted it to do, and then from there I could refine the code and take advantage of the functional features as I learned them. It's a nice way to learn which features from the different paradigms are equivalent, and it really lets you appreciate what you gain from using FP.
The most popular Scheme (Racket) comes with an object system, that I almost instantly fell on when I came to it from C#. I don't think there's any substitute to just explaining the problems with OOP.
That depends on how you think about problems, I think. I understand OOP, and have written OOP code for two decades, using languages like Java, C#, Ruby, C++, etc. However, OOP never felt like a natural way to think to me. The first time I worked with a functional programming was an amazing experience, since FP works in exactly the same way I think. I'm not knocking OOP. I think it is great. It just doesn't fit as well with the way I puzzle through problems. Good thing we have options, I suppose.
It's not, unfortunately. Myself and another have started on an exhaustive pattern matching library that utilizes implicit conversion operators, type inference, lambdas, and a well designed fluent interface to provide support for it in C#. Check out, https://github.com/Jagged/OneOf Distributed as DiscU on NuGet.
This has absolutely nothing to do with functional programming.
> delegates, lambdas, list comprehensions, anonymous types
Syntactic sugar.
> higher-order functions, true closures
Java has them too. They're called “objects”.
> a sprinkle of monads
Every higher-order language with strict evaluation (which includes every object-oriented language) already has at least one monad, whose use is pervasive and inescapable.
So, unless you have user-definable monads, where is the improvement?
No, you only have user-definable type constructors that happen to be monads if you jump to a metalanguage. (Whatever formal or informal system you use to reason about C# code.) Inside C#, you don't even have the means to assert that they are monads, let alone take advantage of the fact that they are monads.
That just shows that the result of specializing the monad laws to one specific type constructor, holds. But the monad laws themselves are inexpressible in a general form.
If you can't even postulate a theory (the monad signature and its equational laws), it doesn't make sense to talk about what models of the theory exist (concrete instances).
Its familiar Java/C like syntax, classic use of OOP, enterprise vibes will mean it'll be very familiar and easy for most to pick up. And as you go deeper, it'll introduce you to anonymous delegates, lambdas, true generics, higher order functions, true closures, list comprehensions, anonymous types, type inference, lazy evaluation and even a sprinkle of monads.
With the language extensions, you can get even further.
This is a great way to start learning about FP concepts without even knowing it and it'll make your switch to a more thorough FP language much easier, such as MLs, Lisps, Erlangs, and most proof languages.