I suggest we ...

Simulate higher-kinded polymorphism

F# already has to make trade-offs when doing interop, e.g. it is possible to create a null value for a DU from C#, erased type providers don't work from anywhere but F# etc. Maybe F# could allow for higher-kinded polymorphism within F# code and use dynamic casts at runtime or maybe statically resolved inlining to simulate higher-kinded polymorphism.

492 votes
Vote
Sign in
(thinking…)
Password icon
Signed in as (Sign out)
You have left! (?) (thinking…)
Daniel Fabian shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

16 comments

Sign in
(thinking…)
Password icon
Signed in as (Sign out)
Submitting...
  • Alexei Odeychuk commented  ·   ·  Flag as inappropriate

    I support exercitus vir. This issue really requires some kind of official response. Either decline it (and explain why) or approve it in principle, but not answering just keeps our votes from being used for other valuable suggestions.

  • exercitus vir commented  ·   ·  Flag as inappropriate

    I just want to repeat my question from about one year ago, because I would really appreciate some comments (concerns, feasibility, effort) from the F# team on this:

    "Any comment from Don Syme or the F# Software Foundation Language Group on the chances of simulating higher-kinded polymorphism in the near future?

    I think this is a really important feature. Many expert functional programmers forego F# because they think can't take a language serious that does not have it. The F# community is losing a lot of potential expert functional programmers [because of this]."

    This issue being more than 2 years old requires some kind of official response. Either decline it or approve it in principle, but not answering just keeps our hopes up and keeps our votes from being used for other feature requests.

  • exercitus vir commented  ·   ·  Flag as inappropriate

    Any comment from Don Syme or the F# Software Foundation Language Group on the chances of simulating higher-kinded polymorphism in the near future?

    I think this is a really important feature. Many expert functional programmers forego F# because they think can't take a language serious that does not have it. The F# community is losing a lot of potential expert functional programmers do to this.

  • Greg Rosenbaum commented  ·   ·  Flag as inappropriate

    This can only be practically implemented using statically resolved inlining (or reflection) because of constraints in the IL type system (this is where reified generics bites you in the ass!). Here is what an fmap function (as described by phylos) might look like:
    https://gist.github.com/Springwight/0368e8e7d7aec8b77e68

    I really don't see it as a technical challenge though, considering how much effort has already gone into the inlining system. It's more like, "do we need to see this in the language?" It's something that's very unlikely to be used by anyone except library developers, but it will help those library developers a lot.

  • Phylos commented  ·   ·  Flag as inappropriate

    In a recent Reddit post related to F# adoption, I saw a great comment from "TarMil" on higher kinds that I believe is worth repeating to illustrate their usefulness. Here is that comment in full ...

    "Basically higher kinds are a type system for types: just like a value has a type, a type has a kind. And just like a function can take other values as arguments, a type variable can take other types as parameters. So where in F# you can have a parameterized type T<'a>, in Haskell the T part itself can be a type variable.

    For an example of the usefulness, see how in F# we have a whole bunch of similar functions:
    List.map : ('a -> 'b) -> list<'a> -> list<'b>
    Array.map : ('a -> 'b) -> array<'a> -> array<'b>
    Seq.map : ('a -> 'b) -> seq<'a> -> seq<'b>
    Option.map : ('a -> 'b) -> option<'a> -> option<'b>
    Event.map : ('a -> 'b) -> Event<'a> -> Event<'b>
    // Not in the standard library, but easy to implement:
    Async.map : ('a -> 'b) -> Async<'a> -> Async<'b>
    // etc.

    In Haskell, you can have a single function fmap, whose type (with an F#-like syntax) would be:
    fmap : ('a -> 'b) -> 'T<'a> -> 'T<'b>

    where (again in a hypothetic F#-like syntax):
    'T : Type -> Type
    // 'T takes a type as parameter and returns a type

    and this function has different implementations for different 'Ts. You can then use this function to write your own functions that can be called on any "mappable" type, and will do the right thing according to the type of the value passed.

    (I gave the example in Haskell because the way to do this in OCaml is more convoluted.)"

  • John Azariah commented  ·   ·  Flag as inappropriate

    1) Even without higher-kinded currying, being able to abstract over Monads and Functors without losing type inference would be pretty helpful. Doing that kind of thing in Scala is pretty painful.

    2) I'm not sure we need to include Scala-style implicits! I find them a way to reduce the transparency of the code and severely affect the ability to comprehend the code - although it may simply be my naivete!

  • Mauricio Scheffer commented  ·   ·  Flag as inappropriate

    The best simulation of higher kinds I know is the technique explained in http://www.nut-cracker.com.ar/ . Work on this ended up in two libraries: FsControl ( https://github.com/gmpl/FsControl ) and FSharpPlus ( https://github.com/gmpl/FSharpPlus ), which builds on FsControl.
    It's not perfect by any means (I need to finish a series of posts about it), but I'm already using it in production, and it works just fine (at least the parts I'm using).
    Of course, it would be much better if F# had explicit support for this.

  • Lev Gorodinski commented  ·   ·  Flag as inappropriate

    This would be very useful for higher-order functional programming, along with, to a lesser extent, something like either Scala implicits or Haskell type classes. This can be a slipper slope though - should higher-kinded currying also be supported (aka partially applied type parameters)? If not part of the type system at the core, should F# resort to Scala type lambdas?

  • Don Syme commented  ·   ·  Flag as inappropriate

    I think "until the CLR finally supports it" should be deleted from the title. To my knowledge there is no prospect of the CLR supporting HK polymorphism in any timeframe that matters for the purposes of this discussion.

F# Language

Feedback and Knowledge Base