'In' is a conventional type parameter; its meaning is: 'not defined yet', In scala for instance it is written '_' which clearly states it has a particular meaning.
M is not a conventional type parameter, it's your parametrized type (think container to help reason about it, like List or Array).
A Higher kind type means that the type is not fully defined and need another type param to be completely defined.
So it a function in the space of Types.
As we're in the space of Types, we don't say this function has a type but a 'Kind'.
In the space of types:
String kind is: *
List<String> kind is : *
List (which is T -> List<T> ) kind is: * -> * so List is a 'type function' - with Heinz proposal it is written List<In>
One may think about kind: * -> * -> * It has no additional value and is not required as it is equivalent to: (* -> *) -> *
With Generics code you may not know the Type parameter of the element; List<T>; T is not known
With Higher Kind you may not know the the Type of the container; you just known you'll have one Type function (List is a type function) passed in to defined the type. (think the 'container')
M<In>; M is not known but we know his kind is * -> * so if you may pass an Int; it would then be M<Int> with M not known; (In Heinz implementation of the proposal, applying Int to the type M<In> would be written Of<M<In>, Int>; Of acting as an application at the type level)
Hopefully, he works on the type system to prevent us to have to deal with that boilerplate. :-)
If you think about it it's always just basic application.
This is the gist of the new abstraction.
The beauty of the thing is that you may still impose some constraints on it; say it's something I can filter on: M:Filterable<M, In>, so M is something I can filter on whatever it is.
So there's a lot of valid programs you may now express with this abstraction.
Most of them exploiting a higher degree of factorization, leading to smaller code base, more reusability / less coupling.
It will ease the job of library writers / architects.
This new expressive power in the type system is a corner stone to fully implement Type Classes.
Type classes is a mechanism to extends a type non intrusively.
For instance, Imagine:
There is no Filter related method on List, we don't care, we can provide it afterwards.
- But we can already do that with Lambda!
- Yes but we loose the container type; I would like to have my filter function return a List if the source container type is a List or and Array if the source container is Array (that why Higher Kinds kicks in).
- Ah Ok..
- Ok so I would like to extends List / Array / Whatever without touching those (coz I don't want to fork and maintain the Std).
- But you can't.
- Yes, the only possible thing is to pass all the type specific filtering functions in each method I call in my own code..
- That is too much Boilerplate; hard to maintain, very verbose.. it would be better to just write the types constraints.. no?
- Yes!
- That's Type Classes?
- Yes! :)
- Wow.. o_O
I hope it helps seeing some use cases..
Best,
Stephane