My F# Wish List

F# is a lovely language. I’m really glad it exists, and I love working with it. However, there is some room for improvement! I’ve gathered a list of all the things that I think are “missing” from F# today. A few of these I’ve found on UserVoice since I started compiling this list, and I’ll soon be adding the ones that aren’t there already. I’ll also update this post as I think of more.

1. Named Constraints

I have lots of constraints in my code, things like:

type Thing =
    abstract member Foo : int

let foo<'a, 'b
            when 'a <: Thing
             and 'b : comparison> () =
    failwith "not implemented"

let bar<'a, 'b
            when 'a <: Foo
             and 'b : comparison> () =
    failwith "not implemented"

Repeating those constraints over and over again is so not DRY. I wish I could define that constraint once and just reference it where needed.

2. Compiler as a service

Aside from the fact that C# and VB are getting compiler as a service, there’s the additional justification provided by F# quotations. When you have something as useful as F# quotations, why not provide a method to compile them to good quality code?

3. Type classes

F# doesn’t support type classes, which means that lots of useful things from Haskell don’t port easily. For instance, if you want to use map, you have to specify List.map, Seq.map, SomeOtherThing.map, etc., but with type classes, we could have a single “map” function that would find the right implementation depending on the (static) types it’s called on. There are workarounds, but they’re not the real thing. We need the real thing.

4. Parameterized Modules

One thing I tried to make my constraints DRY was to mention them at the module level:

type Thing =
    abstract member Foo : int

module ThingMod<'a, 'b
            when 'a <: Thing
             and 'b : comparison> =

    let foo () =
        //code that mentions 'a or 'b
        failwith "not implemented"

    let bar () =
        //code that mentions 'a or 'b
        failwith "not implemented"

Of course this isn’t supported at all, but I can’t see a reason why it shouldn’t be.

For that matter, it’s a shame that the full ML module system isn’t supported. I really wish we could have either ML modules or type classes. Don’t need both, but do need one or the other.

5. Better syntax for anonymous functions

I know it’s traditional, but (fun x –> expr) is too clunky when C# is doing x  => expr.

6. Macros, campl4 style or otherwise

Not having macros is limiting. You don’t need macro support often, but when you need it, you need it.

7. Better Intellisense

Intellisense for F# in VS 2012 is worlds better than in 2010, but it’s nowhere near as good as the C# support. Needs to work as well for F# as it does for C#.

8. Refactoring support

This is required in today’s world. ReSharper, I’m looking at you, too. 

9. Folder Creation in Solution Explorer

I can have folders in my F# project, I just can’t create them in Visual Studio. Disappointing. I can work around by editing the fsproj file, but I shouldn’t have to.

10. More F# Developers at Microsoft!

Come on, Microsoft! Your F# developers are doing great work, but you need more of them! It’s unacceptable that some Visual Studio features don’t work with F#, that things like Silverlight and Windows 8 get released with caveats like “F# is supported, but you have to use C# to build the front end.” Stop pretending this is a language that’s only useful for heavy computer science – it’s a general purpose language!

4 Comments

  • Radek Miček wrote:

    Camlp4 would make IntelliSense very hard or impossible. But it would be nice to have some mechanism for syntax extensions which is IntelliSense friendly.

  • For 3., the fact that generics are reified makes type classes not worth it in terms of cost benefit.

    4. is a good idea but full ML modules are I believe hampered by the .NET object system but I am not 100% square on that.

    Arguably, for most cases where type classes or modules would be great; constraints, abstract classes, interfaces,SRTPs and or object expressions should suffice.

    They could do with making their statically resolved type parameters story cleaner however.

    I agree with all of the rest, especially 6,5, 2 in that order. Computation Expressions, Type providers and quotations are already 40% of the way to macros but there is some kind of an ideological barrier halting full macros.

    @Radek – unless I have misunderstood you, check Nemerle for a language that has intellisense yet great syntax flexibility.

  • > BETTER SYNTAX FOR ANONYMOUS FUNCTIONS

    You should be thankful. Back in my language (C++11), we have to write out our types, both ways, in the snow!

    // this is a lambda expression
    [=](SomeArgumentType x) // types not optional
    { // neither are the brackets, or the return keyword
    return x; // thankfully, return type is inferred – sometimes :-/
    } //phew, finally done!