I suggest we ...

Provide covariance/contravariance language support with syntaxes in F# in sync with covariance/contravariance in C#/VB

Covariance/contravariance has its beginning in CLR 2.0 and also with the introduction of generics in .NET 2.0 (also in F#, C# and VB)

Then in C# 4.0 and VB 10, we have covariance/contravariance supports in the language itself. Currently we don't have support for these covariance and contravariance in F#.

I know it is a runtime feature of CLR 2.0 and 4.0 and I don't want to play catch up with C# and VB.

But this covariance/contravariance support in C# and VB are powerful to use and also have proven to provide cleaner and clearer ways to understand the code and variances in the types, especially when using parameterized generic types.

This is not the same as this feedback:

but we can use that OCaml syntax as well for starter.

This feature should also be constrained to only use covariance/contravariance in interfaces and delegates just like in C# and VB, but F# may provide more supports for other types such as events.
An example of this is the way F# has provided the capability to create extensions to properties and methods, not just methods only in C# and VB.

NOTE: Moved from http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3942302-provide-covariance-contravariance-language-support as suggested by Don Syme.

150 votes
Sign in
Sign in with: Facebook Google
Signed in as (Sign out)
You have left! (?) (thinking…)
Eriawan Kusumawardhono shared this idea  ·   ·  Flag idea as inappropriate…  ·  Admin →


Sign in
Sign in with: Facebook Google
Signed in as (Sign out)
  • Kirill Katsnelson commented  ·   ·  Flag as inappropriate

    Jack Pappas commented · March 23, 2014 5:42 AM
    > F# already does support a bit of contravariance via "flexible types". Flexible types don't seem to be used very often except with the 'seq<_>' type

    Unfortunately, this is not as simple as that. Lacking covariance support, even though e. g. List<'t> can be passed as #seq<'t>, double-lifting into the seq monad is impossible, and the type List<List<'t>> would not match the type #seq<#seq<'t>>; in fact, the inner '#' even makes no sense in such a type annotation, as it requires respecting the covariance of the lifting functor. As far as I understand, no amount of type annotations, even compile-time resolved (the ^t types) can simulate covariance even in this simple example. So the feature is pretty much deeper and much more useful that it might seem at the first sight!

  • Mark Laws commented  ·   ·  Flag as inappropriate

    As the tweet from Erik Meijer linked below would suggest, F# lacks this due to its implications for type inference. Don Syme made a post about this same issue nearly ten years ago: http://osdir.com/ml/lang.fsharp.general/2008-09/msg00043.html

    It would be a shame for F# to suffer for the sake of compatibility with a "feature" that's a corner case even in C# and VB.

  • Bryan Edds commented  ·   ·  Flag as inappropriate

    Please don't do this. If you look at how badly variances complicate scala code and it's type system while realizing how surprisingly non-useful the feature is in practice (which is precisely as Jon H says), you realize such a feature is a net loss.

    If you're wanting variance for interop, just remind yourself how much smaller this problem is, and how much easier it is to work around, than all the other problems with writing interop code.

  • Eriawan Kusumawardhono commented  ·   ·  Flag as inappropriate

    Thanks for your nice comment, Jack!

    IMHO, this is not just a nice feature to have, but it should be nice to have.
    It's because the nature of F#'s strong typing, therefore it should span to strict and strong covariance and contravariance type.
    These covariance and contravariance support is already supported deep inside the .NET CLR since .NET 2.0, so there should be a strong reason to leverage and promote this powerful runtime feature into language feature, not just C# 4.0 and VB 10 has done.

  • Jack Pappas commented  ·   ·  Flag as inappropriate

    This would be a nice feature to have. Even if it were infrequently used in F#-only code, it would be very handy to have when implementing libraries to be consumed from C#.

    BTW, F# already does support a bit of contravariance via "flexible types". Flexible types don't seem to be used very often except with the 'seq<_>' type; if co-/contra-variance are properly supported in F# (a la C# 4.0), flexible types could be deprecated in favor of the variance annotations.

    If this feature is implemented, I'd prefer it use the C#-style "in" and "out" keywords instead of OCaml's +/- syntax; I think the keywords are easier to read, they'll stand out when highlighted in an IDE, and it'll make it easier for C# developers to learn F# (or at least, they'll be able to re-use existing knowledge about the in/out keywords).

  • Jon Harrop commented  ·   ·  Flag as inappropriate

    FWIW, I used OCaml for many years and never once found a use for co/contravariance in real code. There are some corner cases in F# with interop with OO libs like WPF but these are rare IME.

    On a related note, I would like implicit upcast when creating a literal list or array of subtypes like let myControls : Control list = [Label(); Button()].

F# Language

Feedback and Knowledge Base