This is definitely an area where Microsoft has lead the market, not followed it.
This is just adding more functional programming aspects to their dominant language.
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
[2] https://github.com/louthy/language-ext/blob/type-classes/Lan...
[3] https://github.com/louthy/language-ext/blob/type-classes/Lan...
[4] https://github.com/louthy/language-ext/blob/type-classes/Lan...
[5] https://github.com/louthy/language-ext/blob/type-classes/Lan...
The new model used by .NET Core is to make everything a NuGet package; and not a single big one, but small packages comprising one particular bit of functionality, each of which can then be versioned separately. For example, collections are a NuGet package:
https://www.nuget.org/packages/System.Collections/
With this model, it's possible to iterate on the API much faster, so my expectation would be to see functional APIs in the standard library spread much faster from now on.
I could go on, but there's not a huge point to moaning about it, which is why I decided to do something about it. I'm not sure if it's even possible for there to be an official functional BCL without it being a totally new set of packages. It's something that F# would benefit from too.
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.
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/concept...
There seems to be no control, no feature lock, no "our language will be like language x" or definition they follow. It seems more like they listen to the whole community of developers.
All of them.
When I say "riding the wave", what I mean is that they are adding functional features as the regular OOP/imperative programmers in the mainstream are done "accepting" the previous ones they added, as opposed to adding everything in one shot and have people get overwhelmed.
I didn't mean they were following a wave or anything. Analogies are hard.