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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  2. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →
  3. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
  4. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
  5. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →

    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

  6. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    7 comments  ·  Flag idea as inappropriate…  ·  Admin →
  7. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →
  8. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    3 comments  ·  Flag idea as inappropriate…  ·  Admin →
  9. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
  10. 3 votes
    Vote
    Sign in
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  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.

  11. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
  12. Allow access modifies to auto properties getters and setters

    member val Property = 10 with get, private set

    30 votes
    Vote
    Sign in
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  13. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    4 comments  ·  Flag idea as inappropriate…  ·  Admin →
  14. 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.

    8 votes
    Vote
    Sign in
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
  15. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
  16. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  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.

  17. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →

    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

  18. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  19. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    3 comments  ·  Flag idea as inappropriate…  ·  Admin →
  20. 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
    (thinking…)
    Sign in with: Facebook Google
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
← Previous 1

F# Language

Feedback and Knowledge Base