Description
tl;dr
Haskell has monads
Monads are like bacon
C# needs bacon
Introduction
I have a mad craving for higher kinded polymorphism in C#.
And I have no blog to call my own, so here's an essay on this stuff.
That's a fancy name with a lot of crazy type theory and papers behind it, but if you have an understanding of how generic types work in C#, the concept is not terribly hard to understand.
What C# with a taste of bacon would look like
public static T<A> To<T, A>(this IEnumerable<A> xs)
where T : <>, new(), ICollection<>
{
var ta = new T<A>();
foreach(var x in xs) {
ta.Add(x);
}
return ta;
}
...
{
var data = Enumerable.Range(0, 20);
var set = data.To<HashSet<>, int>(); // sorcery!
var linkedList = data.To<LinkedList<>, int>();
var list = data.To<List<>, int>();
}
What is going on here?
where T : <>, // 1
new(), // 2
ICollection<> // 3
- T is constrained to be a generic type definition with one type parameter.
- In CLR lingo: T is a generic type of arity 1
- In type theory lingo: T is a type constructor of kind
* -> *
- Also it should have a default constructor
- And it should implement
ICollection<>
(meaningfor each type X, T<X> implements ICollection<X>
)
Using this you could convert an IEnumerable<T>
to any other type that is a collection.
Even all the ones you have never thought about, including the weird ones from libraries which do not get a whole lot of support because nobody uses them (except of course you).
Like HashSet
(such a weird collection) or LinkedList
(you would need to be crazy).
They are fine citizens of System.Collections.Generic
and very useful, yet they don't get the love they deserve, because they are not as famous as List<>
and implementing To...()
methods in Linq for all of them would be a painful task.
However, with higher kinded polymorphism, they could all get a general concise implementation.
Where's the rest of that bacon?
That general conversion function is just the tip of the iceberg.
You can do all kinds of crazy transformations with higher kinded polymorphism.
And since it allows for such lovely abstractions you only have to implement them once.
Or better yet: Somebody else implements them in a NuGet package and you don't need to care.
Composition over coding.
Haskell? Is that a dog's name?
That NuGet package could be called something neat and concise like, say, Prelude. Yes, what a fine name!
There are some other party poopers, but the lack of Higher Kinded Polymorphism is the biggest road block in stealing all the juicy bacon from the Haskell community.
You know how Linq is awesome?
Do you also know how Linq is an implementation of the List Monad? (kind of)
Well, there are lots of more Monads in Prelude and most of them are awesome.
And currently a bitch to implement in C#.
Plus, HKP would allow to abstract on the concept of Monads!
And on concepts like Tuples
(never heard of them), Functors
(not what you're thinking), Arrows
, Categories
and all the crazy math that comes with them.
I've put together a gist of how wonderful this would be in combination with some other features for implementing Maybe.
I don't know what you're talking about, but it sounds expensive
Let's first look at a summary of the benefits that HKP would bring to C#
- This feature would make C# the most relevant functional programming language with sub-typing and strong static type checking
- A natural extension to the work done by the Linq team
- A natural extension to generics
- Much more natural porting of Haskell code (think about it: years upon years of research on bacon finally in a consumable form)
- A real implementation of the Maybe monad (about time)
- More expressiveness without sacrificing static typing
- HKPs allow something kind of Meta-programming without the nonsense. Whoever used C++ before knows how easily template programming becomes a nightmare. On the other hand, Haskell programmers are delighted by their juicy type system.
- Have I mentioned bacon?
Now let's talk about work:
- Before anything else, a proper implementation would require CLR support
- That would be quite involved, but not impossible. Also I believe it can be implemented as a strict extension to the current metadata without breaking existing libraries
- As a consequence, the F# crowd would benefit from this. I bet they are overjoyed to hear about bacon
- As another consequence, implementing Haskell on top of .Net would be much less of a pain
- C# Syntax
- In C# we can already refer to generic type definitions in
typeof()
as intypeof(IDictionary<,>)
- I think the
where T : <,>
clause seems neat, but is probably not powerful enough (no way to constrain variance on T's parameters or 'swap' parameters for implementations)- maybe more like
where T<,> : <U, X>, IDictionary<X, U>
- or rather
void Foo<A<B, C>, D>() where A<B, C> : IDictionary<C, B> where B : class
- maybe more like
- Well, the syntax needs work.
- In C# we can already refer to generic type definitions in
- Type checking
- it's not work if it's fun
But I'm a vegetarian
Think of Bacon
as an abstract higher kinded type class with non-carnivorous implementations