I suggest we ...

Support for type classes or implicits

(Updated the suggestion to "type classes or implicits", and edited it)

Please add support for type classes or implicits.

Currently, it's possible to hack type classes into F# using statically resolved type parameters and operators, but it is really ugly and not easily extensible.

I'd like to see something similar to an interface declaration:

class Mappable =
abstract map : ('a -> 'b) -> 'm<'a> -> 'm<'b>

Existing types could then be made instances of a type classes by writing them as type extensions:

type Seq with
class Mappable with
member map = Seq.map

type Option with
class Mappable with
member map = Option.map

I know that the 'class' keyword could be confusing for OO-folks but I could not come up with a better keyword for a type class but since 'class' is not used in F# anyway, this is probably less of a problem.

392 votes
Vote
Sign in
(thinking…)
Sign in with: Facebook Google
Signed in as (Sign out)
You have left! (?) (thinking…)
exercitus vir shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →

18 comments

Sign in
(thinking…)
Sign in with: Facebook Google
Signed in as (Sign out)
Submitting...
  • Don Syme commented  ·   ·  Flag as inappropriate
  • Radek Micek commented  ·   ·  Flag as inappropriate

    > What happens if you use two libraries that each instantiate the same typeclass for the same type in a different way?

    @Kurt Doesn't this problem exist with protocols too? What should happen when two different assemblies implement the same protocol for the same type in a different way?

    AFAIK in Haskell this leads to failure when linking. In Scala this is resolved by scoping rules for implicits (which is IMO better than Haskell).

    > And how do typeclasses work with subtyping?

    This could be derived from implicits.

  • Kurt commented  ·   ·  Flag as inappropriate

    I haven't given this any votes because what I've missed is some sort of retro-active interface implementation, like is possible with protocols in Clojure and recently swift. So I voted for this one instead:
    https://fslang.uservoice.com/forums/245727-f-language/suggestions/5665042-allow-extension-interfaces
    because it is more focused.

    Typeclasses solve that problem but protocols seems to me like a solution that is closer to the existing design space of F# (i.e. a functional first language with OO concepts like subtyping). Typeclasses have many extensions - functional dependencies, overlapping instances, etc that are essentially research problems. What happens if you use two libraries that each instantiate the same typeclass for the same type in a different way? And how do typeclasses work with subtyping?

    Finally proposing an idea for A or B (even if A and B are related) draws votes away from more focused suggestions. (e.g. this suggestion has something for everyone so it's not clear what I'm voting for here. Even the original poster commented they don't really want implicits...)

  • Radek Micek commented  ·   ·  Flag as inappropriate

    What about implementation similar to type providers? For each parameter annotated with [<Witness>] attribute where the argument is not given explicitly in the code the compiler would call all witness providers in the scope to generate the argument. If only single witness is generated then this witness becomes the argument otherwise it's an error.

    Additionally if there is a single value in the scope which can be used as the argument then it is used as the argument and witness providers are not used.

  • Gusty commented  ·   ·  Flag as inappropriate

    I know you were not talking about FsControl (http://github.com/gmpl/FsControl) but in the post you mentioned (now moved to http://nut-cracker.azurewebsites.net/typeclasses-for-fsharp) I described a technique which inspired me later to develop FsControl, which runs in F# 3.0 so you don't need to use operators at all. Support for this technique (or similar) at the language level (not CLR) will be nice.

  • exercitus vir commented  ·   ·  Flag as inappropriate

    I was not asking for implicits originally because I am not a big fan of implicits. Implicits can be abused to make code less type safe (e.g. converting floats to ints). They also feel hacky to me if you only want is type classes. Adapting types (implicits in Skala) is also less efficient that calling the functions directly (type classes in Haskell).

    I would prefer pure type classes and you could leverage the member constraints implementation of F# for a clean implementation of type classes in F#.

  • David Ellis commented  ·   ·  Flag as inappropriate

    I think this is the biggest missing piece to F#. F# needs some kind of support for ad-hoc polymorphism. Haskell has type classes and clojure has protocols. F# needs type classes. If I could use all my votes on this, I would.

  • Craig Stuntz commented  ·   ·  Flag as inappropriate

    One possible keyword might be

    type class Mappable = ...

    That reads well and doesn't introduce any new reserved words. It does introduce ambiguity into the grammar, though.

  • exercitus vir commented  ·   ·  Flag as inappropriate

    Daniel and Gusty,

    I was not talking about FsControl and I have not tried FsControl. The script issue occurs when you use the solution presented in http://www.nut-cracker.com.ar/index.php/typeclasses-for-fsharp

    I personally do not care about support at the CLR level. It would already be great if it was an F#-only solution like units of measure and statically resolved type parameters.

  • Gusty commented  ·   ·  Flag as inappropriate

    "...It's not extensible" It is extensible, just orphan instances are not supported.

    "...you need to overload unused operators" this was due to a bug in F# parser, since the introduction of F# 3.0 this is not longer required.

    Regarding the script issue, I really don't get it, could you possible open an issue in https://github.com/gmpl/FsControl/issues describing this problem?

    I personally think F# can add Typeclass support requiring inline functions instead of support at the CLR Level. The same applies to Higher Kinds.
    So the argument "this is a suggestion for the CLR team" is not valid, at least that's not what I'm suggesting.
    To avoid the problem Don Syme mentions in the video, just keep ignoring extensions methods in overload resolution and create a "prelude" for existing types (that's the goal of FsControl).

  • Daniel Fabian commented  ·   ·  Flag as inappropriate

    Whilst, I would love to see this, I think for it be actually useful, we need higher-kinded polymorphism. As it stands now, even if you were able to define type classes, your Mappable would not compile, because 'm<'a> cannot be expressed with the .net type system.

    The technique to simulate type classes has actually evolved somewhat and is _slightly_ less hacky now. E.g. you no longer need a special operator, etc. https://github.com/gmpl/FsControl

  • Will Smith commented  ·   ·  Flag as inappropriate

    Really good post about it. Thanks for the link.

    It definitely feels like a hack if you try to make it behave exactly like Haskell.

F# Language

Feedback and Knowledge Base