F# Language

This User Voice was for suggestions about the future evolution of the F# Language and Core Library.

I suggest we ...

You've used all your votes and won't be able to post a new idea, but you can still search and comment on existing ideas.

There are two ways to get more votes:

  • When an admin closes an idea you've voted on, you'll get your votes back from that idea.
  • You can remove your votes from an open idea you support.
  • To see ideas you have already voted on, select the "My feedback" filter and select "My open ideas".
(thinking…)

Enter your idea and we'll search to see if someone has already suggested it.

If a similar idea already exists, you can support and comment on it.

If it doesn't exist, you can post your idea so others can support it.

Enter your idea and we'll search to see if someone has already suggested it.

  1. Optionally relax signatures of -X, sin X, cos X to allow use w.r.t. subtyping

    See https://github.com/Microsoft/visualfsharp/issues/799

    type Base(x : int) =
    member self.X = x
    static member (~-) (a : Base) = Base(-a.X)
    static member (+) (a : Base, b : Base) = Base(a.X + b.X)
    static member Cos(a : Base) = Base(2*a.X)

    type Derived(x : int) =
    inherit Base(x)

    let a = Base(1)
    let minusa = -a // OK
    let cosa = cos a // OK
    let twoa = a + a // OK
    let b = Derived(1)
    let minusb = -b // Compile error
    let cosb = cos b // Compile error
    let twob = b + b // OK

    3 votes
    Vote
    Sign in
    Check!
    (thinking…)
    Reset
    or sign in with
    • facebook
    • google
      Password icon
      I agree to the terms of service
      Signed in as (Sign out)
      You have left! (?) (thinking…)
      1 comment  ·  Admin →
    • Allow implementation of abstract slots with generic return type instantiated at type 'unit'

      The behavior described here,

      http://stackoverflow.com/questions/26296401/why-is-unit-treated-differently-by-the-f-type-system-when-used-as-a-generic-i

      is quite surprising to someone coming from other typed FP languages. The fact that a generic type parameter can't be unit makes the whole generics abstraction feel a bit leaky and hacky, which isn't great publicity, as F# actually has a lot of great ideas.

      In practice this comes up when implementing type indexed values of various sorts, as an interface is an ideal and natural way to do that, and of course one often wants to have a sometype<unit> value. The compiler error is rather surprising as well, as it implies the object expression…

      7 votes
      Vote
      Sign in
      Check!
      (thinking…)
      Reset
      or sign in with
      • facebook
      • google
        Password icon
        I agree to the terms of service
        Signed in as (Sign out)
        You have left! (?) (thinking…)
      • Expand support for byref to match C# 7

        C# is adding support for byref locals and returns (see https://github.com/dotnet/roslyn/issues/118, slated for milestone 1.3). This will result in many libraries that expose these features (which the CLR already supports), but methods with such return types aren't currently usable from F#. F# already supports byref locals, but doesn't support implementing byref-returning methods nor does it support calling byref-returning methods.

        At a minimum, F# should support calling byref-returning-methods (e.g. SomeRefReturningMethod(x,y,z) <- w), since C# users will be creating methods like these and being unable to call them will limit F#'s reach.

        It would be nice if on top of that…

        14 votes
        Vote
        Sign in
        Check!
        (thinking…)
        Reset
        or sign in with
        • facebook
        • google
          Password icon
          I agree to the terms of service
          Signed in as (Sign out)
          You have left! (?) (thinking…)
        • Catch improper use of monadic return in async

          The following code should issue a type checking error since return () should yield an Async<unit> and return 42 should yield an Async<int>.

          let f c =
          async {
          return ()
          printfn "You passed %A and I am returning 42" c
          return 42
          }

          Additionally the following code should issue a warning since the return statement does not actually affect the flow of execution as the name suggests (The printf statement is actually executed).

          let g c =
          async {
          return ()
          printfn "You passed %A and I am returning 42" c
          return ()
          }

          11 votes
          Vote
          Sign in
          Check!
          (thinking…)
          Reset
          or sign in with
          • facebook
          • google
            Password icon
            I agree to the terms of service
            Signed in as (Sign out)
            You have left! (?) (thinking…)
          • DefaultValue attribute should require 'mutable' when used in classes and records

            For structs, adding the DefaultValue attribute to a val declaration (a field) results in a check that the field is mutable, since it doesn't make sense to use an immutable field which only ever has the default value.

            [<Struct>]
            type S() =
            [<DefaultValue>] val x : C

            AssemblyReader.fs(4304,23): error FS0880: Uninitialized 'val' fields must be mutable and marked with the '[<DefaultValue>]' attribute. Consider using a 'let' binding instead of a 'val' field.

            For some reason, this condition is only checked for fields declared in structs. We should likewise give a warning for records and classes:

            type C() =
            [<DefaultValue>] val…

            1 vote
            Vote
            Sign in
            Check!
            (thinking…)
            Reset
            or sign in with
            • facebook
            • google
              Password icon
              I agree to the terms of service
              Signed in as (Sign out)
              You have left! (?) (thinking…)

              Approved for inclusion in a future release of F#.

              Please consider contributing to F# by providing an implementation, with adequate testing. The code to be adjusted is around here: https://github.com/fsharp/fsharp/blob/212c3359bf6d83e30c12e53fd2ef283d3257b328/src/fsharp/PostInferenceChecks.fs#L1422. For some reason, the code is only activated for struct/enum type definitions, but it should also apply to record and class type definitions.

              Don Syme, F# Language Evolution

            • Add System.Collections.ICollection implementations to F# list/set/map

              ICollection is a useful interface that inherits IEnumerable. Inputs implementing ICollection are utilized by libraries such as LINQ, Nessos.Streams and MBrace in order to optimize partitioning of data. Curiously, none of the F# collections (list/set/map) implement ICollection (however the latter two do implement ICollection<T>, which is a different interface designed for mutable collections). It is currently impossible to extract the length/count of a boxed list/map without performing some sort of reflection, which is not always desirable.

              I suggest that future versions of F# core implement this.

              See also https://github.com/Microsoft/visualfsharp/issues/570#issuecomment-128000307

              10 votes
              Vote
              Sign in
              Check!
              (thinking…)
              Reset
              or sign in with
              • facebook
              • google
                Password icon
                I agree to the terms of service
                Signed in as (Sign out)
                You have left! (?) (thinking…)
              • Add "complement" and "logicalNot" operators to resolve the confusion with "~~~"

                When used on user-defined types, the ~~~ operator resolves to op_LogicalNot rather than the expected op_OnesComplement. See https://github.com/Microsoft/visualfsharp/issues/457#issuecomment-104900399 for a workaround.

                This should be fixed FSharp.Core. An attempt to fix this transparently failed, see https://github.com/Microsoft/visualfsharp/pull/458.

                A plan to address this going forward is at https://github.com/Microsoft/visualfsharp/pull/458#issuecomment-127711336 but will require an update to FSharp.Core.

                1 vote
                Vote
                Sign in
                Check!
                (thinking…)
                Reset
                or sign in with
                • facebook
                • google
                  Password icon
                  I agree to the terms of service
                  Signed in as (Sign out)
                  You have left! (?) (thinking…)
                • Extend custom numeric types to support floating point literals

                  Currently you can define custom numeric types for integer values.
                  It would be nice to be able to handle floating point values too, e.g.

                  type complex = Complex of double * double
                  type imaginery = Imaginery of double
                  with
                  static member (+) (lhs:double,Imaginery(rhs)) = Complex(lhs,rhs)

                  module NumericLiteralI =
                  let FromZero () = Imaginery 0.0
                  let FromOne () = Imaginery 1.0
                  let FromInt32 (x) = Imaginery (double x)
                  let FromInt64 (x:int64) = Imaginery (double x)
                  let FromDouble (x:float) = Imaginery x // extension

                  let polar = 1.5 + 2.5I

                  13 votes
                  Vote
                  Sign in
                  Check!
                  (thinking…)
                  Reset
                  or sign in with
                  • facebook
                  • google
                    Password icon
                    I agree to the terms of service
                    Signed in as (Sign out)
                    You have left! (?) (thinking…)
                  • Make call syntax simpler for statically resolved member constraints

                    The idea is basically explained by the following code:

                    // this works as expected
                    type Example() =
                    member __.F(i) = printfn "%d" i

                    let inline f (x : ^a) =
                    (^a : (member F : int -> unit) (x, 1))
                    (^a : (member F : int -> unit) (x, 2))

                    f (Example())

                    // this doesn't work
                    let inline f (x : ^a when ^a : (member F : int -> unit)) =
                    // the compiler knows that there must be member F and its signature
                    // so the following should be possible
                    x.F(1)
                    x.F(2)

                    You can also view this code…

                    29 votes
                    Vote
                    Sign in
                    Check!
                    (thinking…)
                    Reset
                    or sign in with
                    • facebook
                    • google
                      Password icon
                      I agree to the terms of service
                      Signed in as (Sign out)
                      You have left! (?) (thinking…)
                    • 3 votes
                      Vote
                      Sign in
                      Check!
                      (thinking…)
                      Reset
                      or sign in with
                      • facebook
                      • google
                        Password icon
                        I agree to the terms of service
                        Signed in as (Sign out)
                        You have left! (?) (thinking…)

                        This is approved for inclusion in a future release of F# subject to an implementation and detailed design. A pull request

                        to implement this feature will be necessary and we encourage contributors to submit one with adequate design detail and

                        testing to http://github.com/Microsoft/visualfsharp. Discussion of the particular version for this to be included in can

                        be made once an implementation is available.

                        Design detail can also be discussed below.

                        Don Syme, F# Language and Core Library Evolution.

                      • Make the result of the dict function implement IDictionary

                        The fact that the type returned by dict doesn't implement IDictionary makes reflection difficult and inefficient, it also make this type different than all other .NET Core Dictionary implementations

                        21 votes
                        Vote
                        Sign in
                        Check!
                        (thinking…)
                        Reset
                        or sign in with
                        • facebook
                        • google
                          Password icon
                          I agree to the terms of service
                          Signed in as (Sign out)
                          You have left! (?) (thinking…)
                        • Allow access modifies to auto properties getters and setters

                          member val Property = 10 with get, private set

                          30 votes
                          Vote
                          Sign in
                          Check!
                          (thinking…)
                          Reset
                          or sign in with
                          • facebook
                          • google
                            Password icon
                            I agree to the terms of service
                            Signed in as (Sign out)
                            You have left! (?) (thinking…)
                            1 comment  ·  Admin →
                          • Override `ToString` for discriminated unions and records

                            It's a pain and dirty to add `override x.ToString() = sprintf "%A" x` to every type in order to make `String.Format()` happy:

                            type T1 =
                            { Id: int
                            Version: string }
                            override x.ToString() = sprintf "%A" x

                            type DU =
                            | C1 of int
                            | C2
                            override x.ToString() = sprintf "%A" x

                            I think it's very easy to teach the compiler generate this override automatically for all user types.

                            181 votes
                            Vote
                            Sign in
                            Check!
                            (thinking…)
                            Reset
                            or sign in with
                            • facebook
                            • google
                              Password icon
                              I agree to the terms of service
                              Signed in as (Sign out)
                              You have left! (?) (thinking…)
                            • Cartesian product function for collections

                              It's often useful to compute the Cartesian product (cross join) of two collections. I always end up writing something like this:

                              let cross xs ys =
                              seq {
                              for x in xs do
                              for y in ys ->
                              x, y
                              }

                              I think it would be useful to have this in the standard collection modules.

                              7 votes
                              Vote
                              Sign in
                              Check!
                              (thinking…)
                              Reset
                              or sign in with
                              • facebook
                              • google
                                Password icon
                                I agree to the terms of service
                                Signed in as (Sign out)
                                You have left! (?) (thinking…)
                              • Record type inference suggestion

                                Note that if the record {a: int; b: int} is declared last, then type + argument name type inference will not work. Switching the order around resolves the issue. However, this behaviour can be a little mentally jarring.

                                The lightweight syntax is very useful. It'd be great to strengthen it up.

                                module Eg1 =
                                type AB = {a: int; b: int}
                                type A = {a: int}
                                type B = {b: int}
                                let a = {a=1}
                                let b = {b=2}
                                let ab = {a=1;b=2}

                                module Eg2 =
                                type A = {a: int}
                                type B = {b: int}
                                type AB = {a:…

                                1 vote
                                Vote
                                Sign in
                                Check!
                                (thinking…)
                                Reset
                                or sign in with
                                • facebook
                                • google
                                  Password icon
                                  I agree to the terms of service
                                  Signed in as (Sign out)
                                  You have left! (?) (thinking…)
                                • Add a symbol for FSI to check whether it's in 64 bit or 32 bit

                                  Often I want to reference different libraries based on whether the FSI is running in 32 bit or 64 bit mode. I often have to test two versions of an assembly, and it's enough of a pain just changing the flag every time, let alone change the references. Being able to do:

                                  #if 64_BIT
                                  #r "My64BitLib.dll"
                                  #else
                                  #r "My32BitLib.dll"
                                  #endif

                                  4 votes
                                  Vote
                                  Sign in
                                  Check!
                                  (thinking…)
                                  Reset
                                  or sign in with
                                  • facebook
                                  • google
                                    Password icon
                                    I agree to the terms of service
                                    Signed in as (Sign out)
                                    You have left! (?) (thinking…)
                                    1 comment  ·  Admin →

                                    This is approved for inclusion in a future release of F# subject to an implementation and detailed design. A pull request to implement this feature will be necessary and we encourage contributors to submit one with adequate design detail and testing to http://github.com/Microsoft/visualfsharp. Discussion of the particular version for this to be included in can be made once an implementation is available.

                                    Design detail can also be discussed below.

                                    Don Syme, F# Language and Core Library Evolution.

                                  • Make F# union types like "list" that have no subtypes 'sealed'

                                    The compiled form of the "list" type in F# uses a single class. This is also the case for some other F# union types, e.g. ones which are enumerations where no case carries any data. For these types, the compiled representation of the union type should be marked "sealed" in F# metadata

                                    This is a breaking change w.r.t. hypothetical clients in other .NET languages that take advantage of this, though we know of no such instance in practice.

                                    1 vote
                                    Vote
                                    Sign in
                                    Check!
                                    (thinking…)
                                    Reset
                                    or sign in with
                                    • facebook
                                    • google
                                      Password icon
                                      I agree to the terms of service
                                      Signed in as (Sign out)
                                      You have left! (?) (thinking…)

                                      Considering this approved for F# 4.x or the first possible update after this.

                                      Discussion still very welcome.

                                      Implementations of approved language design items can now be submitted as pull requests to the appropriate branch of http://github.com/Microsoft/visualfsharp. See http://fsharp.github.io/2014/06/18/fsharp-contributions.html for information on contributing to the F# language and core library.

                                      Don Syme, F# Language/Library Evolution

                                    • Restrict "private" for items in namespaces to mean "private to the namespace declaration group" #43

                                      For F# 2.x-4.0, as discussed in thie GitHub thread (https://github.com/Microsoft/visualfsharp/issues/43#issuecomment-70650925), a "private" module or type in a namespace is actually accessible from anywhere in that assembly contributing to the same namespace.

                                      The suggestion is to emit a warning when such an item is accessed from outside the immediate namespace declaration group in which it is declared. For example, we would give a warning if it is accessed from another file in the same namespace in the same assembly.

                                      4 votes
                                      Vote
                                      Sign in
                                      Check!
                                      (thinking…)
                                      Reset
                                      or sign in with
                                      • facebook
                                      • google
                                        Password icon
                                        I agree to the terms of service
                                        Signed in as (Sign out)
                                        You have left! (?) (thinking…)
                                        1 comment  ·  Admin →
                                      • Allow opening of static classes (matching the C# design)

                                        You currently can't "open" a static class e.g. System.Console - only modules or namespaces. We should be able to also open static classes as well.

                                        31 votes
                                        Vote
                                        Sign in
                                        Check!
                                        (thinking…)
                                        Reset
                                        or sign in with
                                        • facebook
                                        • google
                                          Password icon
                                          I agree to the terms of service
                                          Signed in as (Sign out)
                                          You have left! (?) (thinking…)
                                        • Display current parameter type in tooltip for generic function

                                          I posted this on CodePlex (https://visualfsharp.codeplex.com/workitem/172), and Don Syme asked me to put it here as well.

                                          The C# editor in Visual Studio displays the actual parameter types involved in the tooltips for generic class instances and method invocations. The F# editor only does that for objects and methods, but oddly not for F# types/functions; shouldn't this information be quite readily available?

                                          Having this kind of information at hand would especially make it quite a bit easier to follow the transformation of data through pipe chains, even more so as this type of display is also completely absent…

                                          11 votes
                                          Vote
                                          Sign in
                                          Check!
                                          (thinking…)
                                          Reset
                                          or sign in with
                                          • facebook
                                          • google
                                            Password icon
                                            I agree to the terms of service
                                            Signed in as (Sign out)
                                            You have left! (?) (thinking…)
                                          ← Previous 1

                                          F# Language

                                          Feedback and Knowledge Base