4 ms·
They may have been the first, and LINQ was (and is) a truly great feature (I'd love it if they'd expand the grammar, or allow computation expressions like F#);
by louthy 10y ago
They may have been the first, and LINQ was (and is) a truly great feature (I'd love it if they'd expand the grammar, or allow computation expressions like F#); but the problem I've found with trying to do functional programming in C# is that there's no BCL support. Whereas F# has its functional prelude.
I haven't spent much time with Scala, but I get the impression that a lot of the functional stuff is there by default (or at least easily accessibly via Scalaz) and therefore less inertia is needed to write functionally in Scala. Even with LINQ most C# programmers think it's just for querying databases or XML files, they don't realise they have built in monad semantics.
I found that I'd have an immutable collections library over there, that wasn't aware of the Option type in that library over there. (So Map.Find(key) couldn't return an Option<V> for example - this makes composition more difficult).
So although the language has been steadily going in the right direction, there has been less of a concerted effort on the library front. And therefore C# is still behind IMHO.
This is something I've been trying to rectify, by essentially building a functional BCL [1]. I welcome the increased pace of functional features recently. Although sometimes it's frustrating seeing the direction they're going and wishing they'd get there much quicker (expressions everywhere, sum-types, record-types, better type inference).
It's interesting that often C# is held up for its inability to do type-classes or ad-hoc polymorphism. But it is in fact possible with C# today [2] [3], and with zero cost (i.e. no reflection, additional memory allocations, or side-stepping of the type-system). It just causes a massive head-ache of manually provided generic arguments... [4] [5] I'd love it if the Roslyn team took some time to deal with the generic parameters inference story. It would help bring ad-hoc polymorphic types to C#, but it would just be awesome in general.
[1] https://github.com/louthy/language-ext https://github.com/louthy/language-ext
[2] https://github.com/louthy/language-ext/blob/type-classes/LanguageExt.Tests/TypeClassMonad.cs https://github.com/louthy/language-ext/blob/type-classes/Lan...
[3] https://github.com/louthy/language-ext/blob/type-classes/LanguageExt.Tests/TypeClassMonoid.cs https://github.com/louthy/language-ext/blob/type-classes/Lan...
[4] https://github.com/louthy/language-ext/blob/type-classes/LanguageExt.Core/TypeClasses/Monad/Monad.Prelude.cs#L70 https://github.com/louthy/language-ext/blob/type-classes/Lan...
[5] https://github.com/louthy/language-ext/blob/type-classes/LanguageExt.Core/DataTypes/Option/Option.cs#L780 https://github.com/louthy/language-ext/blob/type-classes/Lan...
- plaguuuuuu 10y agoThat is really cool. I'm definitely going to try it out.
- haimez 10y agoArguably, that doesn't count as type classes because it REQUIRES call-site awareness of the implementation. This makes it fully ad-hoc and fully impractical as a useful abstraction. At that point you might as well call a static method without polymorphic parameter types, because it's just as (in)convenient and 100% more readable to the developer maintaining the project after you move on to a better programming language.
- louthy 10y ago> Arguably, that doesn't count as type classes because it REQUIRES call-site awareness of the implementation Yes. I should have stated it's not real type-classes, but it is real ad-hoc polymorphism, which does get you much of the way there. The type-system won't infer the instance, you need to specify it manually. That doesn't make the solution less powerful from a generic programming point-of-view (if anything it makes it more powerful, because you can provide the instance you want to use); however it does make it more awkward to use. > and fully impractical as a useful abstraction. I disagree with this though. Finally being able to define a numeric type, or make types into real monads where a function can declare a constraint that requires an argument to be a monad is a good thing. > At that point you might as well call a static method without polymorphic parameter types From what I can tell, you're thinking of just the call site, but a whole call stack can carry through the constraint, and therefore the call site doesn't need the concrete implementation, it just needs a type that is constrained to the 'type class' (interface). The call site wouldn't know the type of the static method to call in your case. For example with a numeric type: public static T Add<T>(T lhs, T rhs) => // what static method can you call here? If you don't use polymorphic types, then you're not writing generic code, which is what this is for: public static class Math { public int Add(int lhs, int rhs) => lhs + rhs; public double Add(double lhs, double rhs) => lhs + rhs; public float Add(float lhs, float rhs) => lhs + rhs; public decimal Add(decimal lhs, decimal rhs) => lhs + rhs; } What about when you forget: BigInteger, short, byte, long, etc. But with the method I explained above: public interface Num<A> { A Add(A lhs, A rhs); } public struct NumInt : Num<int> { public int Add(int lhs, int rhs) => lhs + rhs; } public struct NumBigInt : Num<BigInteger> { public BigInteger Add(BigInteger lhs, BigInteger rhs) => lhs + rhs; } etc. Any code that works with numeric values can then be written once. I'm sure many C# programmers over the years have cursed over having to write N variants of something that should work with IArithmetic, or INumber, or something similar. This gets around that problem (and without causing any boxing either). So, personally, I think it has value. Even if it's only needed rarely. > because it's just as (in)convenient and 100% more readable to the developer maintaining the project after you move on to a better programming language. My library isn't about the mindset of programmers who are stuck in OO-land with all the conservative nonsense that goes along with it. So although I agree there's a learning curve, I don't think this is too problematic for those who want to write truly generic code. By the way, Microsoft are experimenting with this technique[1] (and new grammar) for future versions of C#. Whether it makes it or not, who knows, but I think it would be a super valuable feature for C#. [1] https://github.com/CaptainHayashi/roslyn/blob/master/concepts/docs/concepts.md https://github.com/CaptainHayashi/roslyn/blob/master/concept...