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. Allow printfn to support repeated arguments

    Rather than:
    printfn "%i %x %A" mySecretNumber mySecretNumber mySecretNumber

    Perhaps an index argument could be added
    printfn "%[1]i %[1]x %[1]A" mySecretNumber

    1 vote
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    4 comments  ·  Flag idea as inappropriate…  ·  Admin →
  2. Code expressiveness: Add loops with test condition in the middle

    Sometimes programmers need to first make a calculation and exit the loop when a certain condition is met. However when the condition is not met there is something else to be done. Hence we need a loop where the test condition is in the middle. That loop was first suggested in 1972 by Ole-Johan Dahl, a Norwegian computer scientist who is deemed to be one of the fathers of object-oriented programming.

    I suggest using the syntax for that loop that requires no new keywords:

    do
    (* indentation to indicate the first part of the loop body *) body-expression
    while test-condition…

    2 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →
  3. Handle null values in Records gracefully instead of crashing with a NRE

    Please see https://github.com/Microsoft/visualfsharp/issues/1044

    Currently, if a nonnull field in a record (e.g. another record, or FSharpList<'T>, ...) is null, .GetHashCode (and potentially other methods) throw a NullReferenceException.

    While these objects are obviously invalid and AFAIK can't be easily created in pure F#, this case sometimes happens out of the control of the user.

    Examples are DataBinding in WPF and Serialization.

    If the external code ever calls .GetHashCode on an object under construction, it will blow up.

    The suggestion is NOT to change anything semantically but to handle null values gracefully where possible to ease the interop with these external libraries.…

    0 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →
  4. 4 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  5. Add triple-questionmark not yet implemented operator (???) from Scala

    In Scala, there is an operator `???`, which is used as a "Convenient as a placeholder for a missing right-hand-side of a method."

    This is defined as follows:
    def ??? : Nothing = throw new NotImplementedError

    In F# I would imagine that we'd define it something like:

    [<GeneralizableValue>]
    let ???<'a> = raise (NotImplementedException())

    Unfortunately, ??? is not a valid name, which is why a library solution won't solve this problem.

    The major merit of including this in F#, is that it provides a standardized way to declare incomplete parts of the code, allowing users and tooling to detect this.

    You…

    11 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    3 comments  ·  Flag idea as inappropriate…  ·  Admin →
  6. Compiler directive for environment variables

    It would be nice to have a compiler directive for environment variables which can be used in string literals.
    This way we can pass different parameters to type providers on a build server.

    [<Literal>]
    let ConnectionString = #env "MY_DB_CONNECTIONSTRING"
    let cmd = new SqlCommandProvider<"...", ConnectionString>()

    4 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
  7. Can we build a pre-processor so we don't have to use the word: let ? Makes the function name standout and saves typing similar to R ?

    Makes the function name standout and saves typing similar to R, ofcourse if it can be done without breaking something else ?

    f := 3 //or ... rather than
    let f = 3

    4 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    4 comments  ·  Flag idea as inappropriate…  ·  Admin →
  8. Add the (..<), (>..) half-open range operators and (>..<) open range operator (from Swift)

    I suggest adding the (..<) and (>..) half-open range operators and (>..<) open range operator to the language in order to reduce risks of introducing off-by-one errors in code.

    There is the (..) closed range operator in F# to generate ranges of consecutive values, but now the language lacks the (..<) and (>..) half-open range operators to generate ranges of consecutive values without the first or last value specified respectively. Furthermore, there is no open range operator (>..<) to generate a range of consecutive values without both the first and last value.

    Syntax suggested:
    a) from Swift:
    1 ..< 10…

    1 vote
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  9. Add the do .. while loops to the language (from Java, C, C++, C#)

    I suggest adding the do .. while loops to F#. This feature would improve the expressiveness of the language and facilitate the migration of large codebases to F# from imperative languages such as Java, C, C++, C#.

    I suggest using time-tested and popular syntax from Java, C, C++, C# (TIOBE TOP 4 languages as of March 2016), but with F#-style indentation instead of {}:

    do
    (* indentation to indicate the body of the loop *) body-expression
    while test-condition

    The difference between the do .. while loop and the already existing in F# while .. do loop is that do ..…

    4 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    3 comments  ·  Flag idea as inappropriate…  ·  Admin →
  10. Code clarity: Remove Object Pascal-style for ... to|downto ... do ... loops from the language (from Swift)

    The for ... to|downto ... do ... loop appears to be a mechanical carry-over from Object Pascal rather than a genuinely F#-specific construct. The for ...to|downto ... do ... loops do not lend themselves to use with sequences and other core F# types supporting IEnumerable interface. It is rarely if ever used in pro-level apps. More F#-typical construction is already available in the language with the for ... in ... do ... loop that has much better readability and expressiveness.

    Example # 1:
    // it provides equivalent behavior to: for i = 1 to 100 do ...
    for i in…

    4 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    3 comments  ·  Flag idea as inappropriate…  ·  Admin →
  11. 26 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  12. Add (^%) f = f to core library

    This allows method chaining with sequences etc need no parens:

    http://stackoverflow.com/questions/36220283/anything-else-similar-to-haskells-in-f-other-than

    Optionally call it ^$ for Haskell users, though it's not exactly the same as Haskell's $. ^% is (imo) the nicest on the fingers.

    2 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  13. Add (binary) search function to Map and Set

    Often in interpolation the nearest collection items to a given value are needed. Map and Set both have a data structure that could be binary searched returning the two nearest neighbours optionally. The function should only be called something like 'nearest' so the implementation isn't exposed.
    At the moment you would have to replicate the collections to be able to do this.

    3 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    2 comments  ·  Flag idea as inappropriate…  ·  Admin →
  14. Code clarity: Dot notation for casting objects to interfaces

    I suggest introducing the dot notation syntax for casting an object to an interface.
    It would be great to write, for example:

    this.InterfaceName.methodName(param1, param2, ..., paramN)

    myObject.InterfaceName.methodName(param1, ..., paramN)

    instead of:

    (this :> InterfaceName).methodName(param1, param2, ..., paramN)

    (myObject :> InterfaceName).methodName(param1, ..., paramN)

    I think the use of one symbol "." instead of four symbols "(", ":", ">", ")" to convey the same idea can improve F# code clarity.
    The syntax suggested would be especially useful in the body of methods of classes that implement multiple interfaces.

    P.S. My suggestion does not mean a breaking change in the F# language. I…

    5 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →
  15. Inlined default argument values

    Instead of

    member __.Foo(?a: int) =
    let a = defaultArg a 2

    it would be great to write it C#-slyle:

    member __.Foo(?a: int = 2)

    6 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  16. custom set the 'last defined'

    Say we implement something like:

    type BinaryOp =
    | And
    | Or
    | Not
    | None

    module test =
    let aMatchFunction (s:string option) = match s with
    | Some s -> printfn "%s" s
    | None -> printfn "(none)"
    // Error This expression was expected to
    // have type string option but here has
    // type BinaryOp

    Some of the F# conventions are nice, and it'd be good to be able to stay consistent with them across our code base if we choose. In this case, I feel we shouldn't be forced to adopt the longhand convention of:

    Option<string>.None just…

    1 vote
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →
  17. allow defining function with generic type parameter within another function

    I encounter cases where I'd like to define a function taking a generic type parameter within another functions.

    type Foo = {Bar: int option; Baz: string option}

    let doSomething () =
    (**)let writer = Console.Out
    (**)let writeOption o =
    (* *)match o with
    (* *)| Some v -> writer.Write(string v)
    (* *)| None -> writer.Write("")
    (**)writeOption foo.Bar
    (**)writeOption foo.Baz

    It's not possible to do that right now and even if I define the function outside at module level (with extra writer parameter), I can't curry it to avoid passing the context (writer) parameter I'm trying to elide to keep my…

    1 vote
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  18. Add constraints to match FSharpType.Is* predicates

    I have a type, CaseSet<'a>, that is only meant to be used with descriminated unions. The only way I've found to enforce this is at runtime using FSharpType.IsUnion. I considered using type providers, but those aren't supported in PCLs.

    I propose adding the following constraints based on the corresponding FSharpType reflection functions.

    function : IsFunction
    tuple : IsTuple
    union : IsUnion
    record : IsRecord
    module : IsModule
    exception : IsExceptionRepresentation

    (I'm not really sure about that last one... I included it for completeness but maybe just testing for some subclass is sufficient?)

    1 vote
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →
  19. add a keyword for module-local construction but public deconstruction of types

    Similar to dependant types, except you wouldn't enforce the predicate on which the type is dependant on to be defined WITH the type.

    This keyword could stop clients of a module from constructing the type, but would allow them to 'see' that it exists, and therefore allow them to deconstruct it for their own use.

    For example, if you want a string constrained to 50 chars, you could have

    type String50 = constrained String50 of string

    let createString50 s = if String.length s <= 50 then Some s else None

    where 'createString50' is a constructor.

    Correct me if I am…

    5 votes
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    1 comment  ·  Flag idea as inappropriate…  ·  Admin →
  20. Support partial record prototypes

    I have a case where I have several related types (categories of parameter sets for an analytics API). I want to create a set of new types such that every category is required in exactly one of the new types, and all of the other categories are optional.

    This is fairly easy to express in a variety of ways in F#, but enforcement becomes difficult. I'd prefer to use record types with a default prototype, but there are no good defaults for the required parameters. I either have to clutter up my types with bona fide classes with constructors, or…

    1 vote
    Vote
    Sign in
    (thinking…)
    Password icon
    Signed in as (Sign out)
    You have left! (?) (thinking…)
    0 comments  ·  Flag idea as inappropriate…  ·  Admin →

F# Language

Feedback and Knowledge Base