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. Code clarity: Make syntax for sequence expressions as simple as syntax for lists

    I suggest simplifying syntax for generating sequences. It would be great to make it as simple as syntax for lists in F#.

    For example,

    let lst = [ 1; 2; 3; 4 ] // allowed
    let sq = seq { 1; 2; 3; 4 } // not allowed, why?
    // error FS0739: Invalid object, sequence or record expression.

    Now, the F# syntax rules allow declaring a simple sequence expression as follows:

    let se = seq { yield 1; yield 2; yield 3 }

    I think syntax rules may well be simplified in that case. It would be more comfortable for…

    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…)
    • Code clarity: To change the default value returned by function Unchecked.defaultof<string> to "" from null

      I suggest changing the default value returned by function Unchecked.defaultof<string> to "" from null. I think the function should return a value of type string indicating an empty string "" as expected by a majority of language users who writes string processing code.
      Null indicates that there is no value at all.

      I am inclined to think from my own experience that null returned by Unchecked.defaultof<string> leads to unnecessary complications in the code dealing with value names of type string, namely in the form of mandatory checks both for "" and null, instead of a check for "" only in…

      2 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 Set.count O(1)

        Seems easy to track items when they are added and removed

        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…)
        • Add Map.count

          Implement Map.count

          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 record inheritance / multiple "inheritance"

            I propose to add multiple ***fields*** inheritance into records:

            type Person =
            { First: string
            Last: string }

            type Foo = { Bar: int }

            type Student =
            inherit Person
            inherit Foo
            { GPA: float }

            let student = { First = "a"; Last = "b"; Bar = 2; GPA = 1.0 }

            Making the same thing with composition results with not such an elegance flat records.

            This approach is used, for example, in Nitra AST DSL, see https://github.com/rsdn/Nitra-Mini-C/blob/master/Nitra-Mini-C/MiniC-ast.nitra#L94

            17 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 overloads of custom keywords in computation expressions

              I've been using custom keywords in computation expressions to write DSLs, and I would have loved to be able to have several signatures for the same custom keyword, in order to make some arguments optional in the expression.

              When you try do it today, there is an error message such as "The custom operation 'myOperation' refers to a method which is overloaded. The implementations of custom operations may not be overloaded"

              I'm aware this is a not-so-used feature, but I'd like to know how hard you think it could be (I would event be willing to have a look at…

              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…)
                1 comment  ·  Admin →
              • Allow record types to implement interfaces just by adding the interface name when compatible

                When a record type already has all the members necessary to impement an interface, it could implement it without having to write the code.

                For instance:

                type IHasAnAge =
                abstract member Age: int

                type Person = {
                Name : string
                Age: int
                } with interface IHasAnAge

                32 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 use to not bind the expression to a name

                  In C#, one can use using(CreateSomeDisposable()) without binding the expression to a name.

                  Same construct in F# is not allowed, forcing a workaround such as

                  use __ = CreateSomeDisposable()

                  allow to make it like this:

                  use CreateSomeDisposable()

                  6 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 →
                  • Hide Obsolete warnings on record initializer not using the obsolete field.

                    Basically the compiler emits a warning even when a obsolete field is not used directly in the source code. Here is a code example showing what I mean:

                    // def version 1
                    type TestRecordV1 =
                    { Field1 : string
                    Feild2 : string }
                    static member Emtpy =
                    { Field1 = null
                    Feild2 = null }
                    // usage
                    let v1var1 = { TestRecordV1.Emtpy with Field1 = "field1" }
                    let v1var2 = { TestRecordV1.Emtpy with Feild2 = "field2" }
                    let v1var3 = { TestRecordV1.Field1 = "field1"; Feild2 = "field2" }
                    let v1access1 = v1var1.Field1
                    let v1access2 = v1var1.Feild2

                    // def version 2 …

                    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…)
                    • Make tuple defined DU cases more consistent with tuple

                      It is possible to pattern match tuples in a flexible way:

                      let a = 1,2

                      match a with
                      | 1, _ -> ()
                      | _ -> ()

                      but it's not possible to do this on tuple defined DU cases, one has to write this:

                      match pat with
                      | SynPat.LongIdent(_, _, _, _, _, _) -> ()
                      | ...

                      which breaks whenever the case definition change (even at place where we don't care of the contents)

                      while supporting this would be friendlier / more resilient to DU case change:

                      match pat with
                      | SynPat.LongIdent _ -> ()

                      or even

                      match pat…

                      9 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 units of measure for standard type aliases

                        Currently there is a support for `float<cm>`, but not `double<cm>`; I should call it `float32<cm>`. Almost in every other position `float` and `double` are completely equivalent (and some programmers prefer `double` over `float`). Shouldn't it be the case for units of measure support?

                        Also, it seems that units of measure are not supported for unsigned types at all. Was it a design decision? I suggest adding these.

                        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…)
                        • Code succinctness: Relax syntax rules for the else branch of an if expression (from Ada 2012)

                          For the sake of code succinctness, I suggest relaxing syntax rules for the else branch of an if expression in two special cases:
                          1) When there is no else branch in an if expression and the type of the if expression is inferred to be bool, then the F# compiler should treat the absent else branch as equal to false, type bool (like in Ada 2012 for if expressions).
                          2) When there is no else branch in an if expression and the type of the if expression is inferred to be option, then the compiler should treat the absent else…

                          0 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 generic type constraints for union and record

                            I suggest that the ability to express the following type constraints be added:

                            when 'T : union
                            when 'T : record

                            This would enable apis which use quotations or reflection over the supplied record or union to be safer.

                            The constraint could be enforced at runtime if unions or records implemented some sort of marker interface, perhaps there is a better way.

                            2 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…)
                            • Code robustness: Types with ranges of admissible values (from Ada 2012)

                              I suggest introducing an aspect that can be applied to declarations of enumeration types, discriminated union types and user-defined numeric types with the aim of specifying the range of admissible values for subtypes derived from base types easily.

                              This suggestion is an extension of my previous suggestions:
                              1) Types with predicates to create subtypes easily (from Ada 2012);
                              2) Types with default initial values specified (from Ada 2012).
                              Please see them for more details:
                              1) https://fslang.uservoice.com/forums/245727-f-language/suggestions/12564486-types-with-predicates-to-create-subtypes-easily-f
                              2) https://fslang.uservoice.com/forums/245727-f-language/suggestions/12800967-types-with-default-initial-values-specified-from

                              Example # 1. Type with range of admissible values specified.

                              type scores = int range 1 .. 100 // admissible values: 1,…

                              5 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…)
                              • Types with default initial values specified (from Ada 2012)

                                I suggest introducing an aspect that can be applied to declarations of enumeration types, discriminated union types and user-defined numeric types with the aim of specifying their default initial values in code easily.

                                This suggestion is an extension of my previous suggestion:
                                Types with predicates to create subtypes easily (from Ada 2012)
                                Please see it for more details:
                                https://fslang.uservoice.com/forums/245727-f-language/suggestions/12564486-types-with-predicates-to-create-subtypes-easily-f

                                Example # 1:

                                type OK = bool [with] default true // type with true as its default initial value

                                Example # 2:

                                type Animals =
                                | Tiger
                                | Lion
                                | Cat
                                | Mouse
                                | Hamster
                                [with] default Cat

                                type Prey =…

                                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…)
                                • Types with predicates to create subtypes easily (from Ada 2012)

                                  I suggest introducing type predicates as an aspect that can be applied to declarations of enumeration types, discriminated union types and user-defined numeric types with the aim of creating subtypes easily.

                                  Suppose, we are concerned with animal species and that we have a
                                  type Animals thus:

                                  type Animals =
                                  | Tiger
                                  | Lion
                                  | Cat
                                  | Mouse
                                  | Hamster

                                  Now suppose we wish to declare subtypes for predators and prey.
                                  So we would like to declare a type Predators embracing Tiger, Cat and Lion, and a type Prey embracing Mouse and Hamster.

                                  I suggest two ways to do this:
                                  1)…

                                  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…)
                                  • Allow basic integer numeric type names in a for loop (from Ada 2012)

                                    I suggest using basic integer numeric type names (namely, sbyte, byte, int16, uint16, int (int32), uint32, int64, uint64) in a for loop meaning to try every value of the type (from Ada 2012).

                                    For example,
                                    let ourSequence = seq { for i in int -> i } // ourSequence : seq<int>

                                    let ourList = [ for i in byte -> i ] // ourList : byte list

                                    for i in sbyte do printf "%A" i

                                    I think it's a good idea to allow basic integer numeric type names in for loops just as in Ada 2012 and treat such types…

                                    2 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 enumeration type names and discriminated union type names in a for loop (from Ada 2012)

                                      I suggest using enumeration type names and discriminated union type names in a for loop meaning to try every value (from Ada 2012).

                                      For example,

                                      a) Enumeration type name in a for loop:
                                      type Animals =
                                      | Tiger = 1
                                      | Cat = 2
                                      | Lion = 3
                                      for animal in Animals do printf "%A" animal

                                      As of today, the F# compiler posts a message: error FS0039: The value or constructor 'Animals' is not defined.

                                      b) Discriminated union type name in a for loop (Ada 2012 does not have discriminated union types, but it has record types with a discriminant…

                                      2 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…)
                                      • Use the in keyword and "|" symbol for membership tests and better readability (from Ada 2012)

                                        I suggest using the in keyword for membership tests (from Ada 2012).

                                        Example # 1:
                                        if x in 1 .. 100 then ... // the in keyword would be especially useful within the if expressions. That form of the if expression has better readability than: if x >= 1 && x <= 100 then...

                                        Example # 2:
                                        match counter with n when n in 1 .. 10 .. 101 -> ... // the when expression here has a succinct form and better readability than the current syntax: match counter with n when [ 1 .. 10 .. 101 ] |>…

                                        6 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…)
                                        • Inline Record Definition in Discriminated Unions

                                          type shape =
                                          (**)| Circle of
                                          (*....*) { centerX : float
                                          (*......*) centerY : float
                                          (*......*) radius : float
                                          (*....*) }
                                          | Rect of
                                          (*....*) { x_lo : float
                                          (*......*) y_lo : float
                                          (*......*) x_hi : float
                                          (*......*) y_hi : float
                                          (*....*) }

                                          Recently Added to OCaml
                                          https://blogs.janestreet.com/ocaml-4-03-everything-else/

                                          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…)

                                          F# Language

                                          Feedback and Knowledge Base