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 flexible types in default constructor constraint

    This would permit,

    let ctor<'a when 'a:(new: unit -> #IWebDriver)> : unit -> IWebDriver = ...
    versus

    let ctor<'a when 'a:(new: unit- > 'a) and 'a :> IWebDriver> = fun () -> new 'a() :> IWebDriver

    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 more flexible layout for constraint syntax

      The following layout of constraints for a sample class should be possible.

      GroupedFixtures<'A, 'B
      when
      'A :> Remote.RemoteWebDriver and
      'A : (new: unit -> 'A) and
      'B :> ServerFixture
      >() as this =

      Presently it almost was but the `new()` constraint use of parenthesis caused problems. currently all the constraints layout forces them on the same line which is not as clear or convenient (note the text, that `>() as this`, is allowed on a separate line):

      GroupedFixtures<'A, 'B when 'A :> Remote.RemoteWebDriver and 'A : (new: unit -> 'A) and 'B :> ServerFixture
      >() as this =

      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 shorthand/literal syntax for creating Maps

        A shorthand/literal syntax or computation expression for building Maps would be nice—something like the following:

        let m = map ["a",97; "b",98; "c",99]

        The shorthand for dictionaries ...

        let d = dict ["a",97; "b",98; "c",99]

        ... is nice, but while Maps implement IDictionary, dictionaries do not play well with Map module functions. One must inevitably convert a dictionary to a Map or create a Map with Map.ofArray, .ofList, or .ofSeq.

        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…)
        • Allow function names to end with a question mark.

          I find it really elegant in some language where predicate functions can end with a question mark.

          Consider `odd? 5` vs `isOdd 5` or `areRelated a b` vs `related? a b`

          There might be some reason why it's a terrible idea grammar-wise or something in F#. I'm still very much a newbie I'm afraid. I apologize if it's featured in a FAQ I missed or even here and I search badly.

          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…)
          • 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…)
            • Improve Discriminated Union Type Inference

              Sometimes the most logical name for an element of a Discriminated Union (DU), is a common concept such as a list
              -- something that you've used before elsewhere.

              The only way around the last resolved resolution is either through namespaces, or by adopting a naming convention.
              Sometimes getting nagged about name overuse can lead to clearer code, but what if our intention is exactly as
              written? In the below, if we named elements to be ListOfA and ListOfB, then the problem goes away.
              Sounds and often is simple, but it can lead to additional code noise and moves us away…

              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…)
              • #r #load via fsi method

                fsi.Load("script.fsx")
                fsi.Reference("bin/debug/someDllReference.dll")

                It would be very useful to be able to fsi.Load / fsi.Reference through type providers, for use by those who are designing them.

                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…)
                • Map keys <--> set compatibility

                  A map's key collection is a set and should be treatable as such. Currently (AFAIK) you must get the keys from the map like so:

                  let keys = Map.toSeq >> Seq.map fst

                  then create a set from the (k,v) seq:

                  let set1 = keys map1 |> Set.ofSeq

                  and then perform your set operation:

                  let common = Set.intersect set1 set2

                  This involves creating a temporary collection and a new set.

                  There are several ways to improve things:

                  (1) Provide a Map.toKeySet & Set.ofMapKeys functions that will directly and efficiently create a new set from the Map's keys. This is straightforward and…

                  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…)
                  • Add Polymorphic Variants (ad-hoc Discriminated Unions)

                    Creating strongly typed data constructs with some level of heterogeneity is often accomplished with DUs so lets take the trivial case of wanting
                    to have lists of floats & ints, ints & strings, and ints & floats & strings
                    We'd need the types -

                    type IntString =
                    | Int of int
                    | String' of string

                    type FloatInt =
                    | Float of int
                    | Int of int

                    type IntFloatString =
                    | Float of int
                    | Int of int
                    | String' of string

                    But in practice using these would require qualified access to make sure you're getting the right case from the…

                    36 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 →
                    • extend ComputationExpression builders with Map : m<'a> * ('a -> 'b) -> m<'b>

                      In many scenarios computation expressions could be executed way more efficiently when having just a little more information.

                      The typical use-case for that would be something like

                      async {
                      let! a = something
                      return 2*a
                      }

                      which currently gets translated to:
                      async.Bind(something, fun a -> async.Return(2*a))

                      By monad laws (borrowed from haskell here) this must be equal to:
                      async.Map(something, fun a -> 2*a)

                      In many scenarios the latter can be implemented with a lot less overhead, so in my opinion it would be profitable to allow users to provide this "shortcut".

                      8 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…)
                      • 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…)
                          • In a pattern match use the record field name as a default binding if none is provided

                            In OCaml we can do,

                            match somrecord with
                            | {foo; bar; baz} -> foo + bar + baz

                            If we don't provide a binding, then the field name is used as the default. In F# we still have to write,

                            match somerecord with
                            | {foo=foo;bar=bar;baz=baz} -> foo + bar + baz

                            This is quite a simple syntactic enhancement, however it's very nice to have. It also pushes us to use the (presumably) well chosen record field names for our variables instead of picking a single letter variable name.

                            Also, in OCaml we get a warning if we don't bind all…

                            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…)
                            • 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…)
                              • Richer literals: TimeSpan/DateTime/Char array/UTF8

                                Combining several suggestions for richer literals

                                - New literals for TimeSpan and DateTime. e.g.

                                "01:02:03"T --> new TimeSpan(1,2,3)
                                "2015-01-02 10:30:00"D -> new DateTime(2015,01,02,10,30,00)

                                - Char[] e.g

                                "abcd"C

                                - UTF8 encoded strings "abc££def"U

                                and indeed perhaps the whole mechanism should be extensible like QZRING literals

                                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 →
                                • Introduce the ?. operator into F#

                                  Since we allow the . operator to reference fields and properties of objects in F#, we're faced with the same problem of null checking that plagued C# until C# 5.

                                  The C# 6 'elvis' operator propagates nulls in a succinct way, and I think that working with objects in F# will be similarly simplified if we introduce it here as well!

                                  16 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 all declarations to be mutually referential and the compiler takes files in any order

                                    With F# becoming more and more multi-editor and cross-platform, it is becoming increasingly difficult to teach all build/edit tools about F#'s file order. The F# community are currently struggling to "update" each new build/edit tool to understand that F# actually needs a file order.

                                    Part of the problem is that there is no standard textual way to specify this file order except as command line arguments, and these are not stored in an editable form. There is no standard way to specify the F# file order. We need an (optional) solution to this problem that is closer to home and…

                                    39 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…)
                                      • implicit upcast of return values

                                        It gets to be very frustrating when working with many C# libraries from F# because F# lacks implicit upcasting of return values. In some cases, this is just annoying. But it is particularly intractable when dealing with libraries expecting Expressions, because upcasting changes how the expression is evaluated by the library. See this question, where in the comments, the author comes to the conclusion that he can't make it work with F#.

                                        http://stackoverflow.com/questions/10647198/how-to-convert-expra-b-to-expressionfunca-obj

                                        There does exist a work-around, but it is quite horrible.

                                        http://www.fssnip.net/c7

                                        Aside from this show-stopping issue, there are many other scenarios where libraries expect implicit upcasts and…

                                        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…)
                                        • Produce System.Linq.Expressions more efficiently

                                          Most of .NET query providers are written in C# and use System.Linq.Expressions. While the conversion Expr->Expression is available it introduces significant penalty: http://stackoverflow.com/questions/32592811/why-is-f-expression-tree-generation-is-much-slower-than-c-can-it-be-made-fast

                                          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