Waning F#

I want to like F#. It’s like what C# should have been 7 years ago. F# has beautifully terse, yet readable syntax. With algebraic data type, duck typing, and computation expressions, the language can lend itself to pretty powerful code.

But I’ve been having some doubts. I’ve slowed down in using the language. My enthusiasm wanes. I’ve written a parser in F#, wrote unit tests in F# for a C# project, and developed an Electron app with the backend in F# (using edge). All these projects have been neglected as of late.

C# and F#

There’s a saying that with each new version of C#, it is stealing all the good bits of F#. C# 6 gave us:

  • Getter-only auto-properties
  • Expression-bodied function members
  • Null-conditional operators

C# 7 will give us:

  • Basic pattern matching on types. I imagine these can be used to simulate discriminated unions.
  • Proper Tuple support!
  • Local functions

Even the next version of C# is planned

  • Non-null references
  • Records
  • With expressions
  • More pattern matching improvements

These features are going to make C# that much more enjoyable to write (and it wasn’t a bad language to begin with)! And each version of C# is separated by about a year. By contrast F# is not gaining features at nearly the same pace. It’s been 17 months since F# 4.0 was released in July 2015 with few features I’d find noteworthy. Sure constructors as first class functions shorten invocations, simplified mutable values (no more ref!) are nice language level features, but aren’t anything to write home about.

Currently F# 4.1 is unreleased, but is somewhat underwhelming:

  • A Result type is nice (similar to Rust’s Result), except whereas Rust has 20 functions under Result, F# only has three. Seems too little, too late
  • Referential modules is kinda nice
  • Struct annotations [<Struct>] and fixed help for some low level code

It’s not as if people think the language doesn’t have any room to grow. Some interesting ideas on the future of the language:

I’m crossing my fingers that moving to Github issue jumpstarts development on some of these features. If F# doesn’t move fast enough, C# is starting to develop some functional libraries.

Everyday Frustrations

Despite enjoying this language for several years I have been unable to spread the adoption. There’s twenty six low-risk ways to use F# at work, yet if you’re not a .NET/Windows shop you can slowly widdle those reasons down to zero. I’ve had much better success showing off Rust tools like csv parser xsv that utilize static linking with musl; allowing us to scp these single 1MB file binaries to far off boxes and have them just work.

I would also like to bring up .NET Core, the future cross platform runtime for .NET apps. It’s new, no doubt, but it has been in development for a couple years and the release candidate for 1.0 was released over a year ago (Nov 5 2015). The F# team should have seen this coming, yet I can not stand developing F# libraries on .NET Core. I run into inexplicable issues like the following. It’s like I’m computer illiterate, and it’s frustrating. I try and use simple and straightforward repos like Chessie for inspiration, but I get confused when I see commits switch a reference from Microsoft.FSharp.Core.netcore to FSharp.Core, and I have no context why. Someone needs to put together a guide.

The visualfsharp repo is keeping tabs on CoreCLR progress. Looks like there is a decent chunk unfinished.

The relationship between the fsharp/fsharp and Microsoft/visualfsharp is odd. I get that the fsharp repo has always been opensourced with the visualfsharp repo add later. I don’t know why the repos are not merged. Kinda looks like Don Syme is just copying code from visualfsharp into fsharp. Having two repos like this seems to only lead to confusion. What’s the difference? One is Windows build and the other one is not? What about .NET Core and the promise of .NET cross platform?

And maybe the worst, syntax highlight is still not available for Jekyll (what this site is built on). F# support was only recently merged into rouge, but kramdown isn’t supporting that version.

I find Type Providers very overrated. I have never used one to a beneficial effect; partly because I work with data samples that are not representative of live, volatile data. I’ve even tried writing my own Type Provider but documentation is limited and error messages are cryptic. Type Providers also impose unnecessary restrictions. For instance, there is a SQLProvider, but one has to have a db connection to compile the code. That seems wrong. What if I’m on a new machine, but I have to get an emergency fix out the door? I’d have to take time to set up a development database, and hope that I had the forethought earlier to make it as painless as possible. Ideally, a Type Provider only generates classes once at initial connection and updates classes on subsequent connections.

Community

I like the F# community, but it does not seem to be making the difference I had hoped. Only F# projects seem to start from the ProjectScaffold that bills itself as the “A prototypical .NET solution”. I’ve used it successfully with a C# project before, it was a great boon, as I’m still kinda shaky when it comes to releasing NuGet packages. It’s not all good even for F# projects. The ProjectScaffold is showing it’s age with commits slowing down and the documentation page using a several year old version of Bootstrap (2.2.1 was released on October 31, 2012). I know that as an open source contributor I can fix all these things, but I don’t know, it’s a little like Not Invented Here syndrome. It’s nice that F# projects can opt-in to an uniform interface, so that users know what to expect, but maybe it would decrease maintenance if the F# community didn’t invent their own interface. There’s other tools that were invented for F#. The F# package manager Paket, the F# task runner FAKE, F# project management tool Forge, F# project file fstoml. In an ideal world, the ecosystem would be unified. A possible counter argument is that the Java ecosystem is split as well (maven vs sbt vs gradle). For the record, I quite enjoy Paket and FAKE, but Microsoft has doubled down on MSBuild and dotnet-cli, so the future seems bleak for Paket and FAKE.

I do not regret spending time in the community, learning the language, and growing my skills in other areas of programming. F# especially introduced me into the world of functional programming and made monads click for me. For that, I will always be thankful.

Speaking of the community, on F#’s Reddit a user said it best:

  1. F# is always going to be second fiddle to C#
  2. Linux/Mac are always going to be second fiddle to Windows/Visual Studio

I agree with the sentiment, and I feel like I have to find an ecosystem that isn’t willing to compromise like F# has. It almost doesn’t matter how nice the base language is if getting a solution to compile and run tests is an exercise in futility.

Conclusion

I’m not giving up on F# yet. I won’t turn my back on it anytime soon. F# holds a dear place in my heart, but I am going to start give C# more of a chance. C# is becoming a more beautiful language with each release, and some of the functional shortcomings can be solved through libraries. Still going to miss that pipe operator though. I’m also going to keep up my learnings in Rust.

Comments

If you'd like to leave a comment, please email [email protected]

2017-10-04 - rei

Spot on. Been a fan of F# since 2008, but I’m beginning to give up.

It’s been over a decade and a lot of the tooling is still kind of awful. Even IntelliSense is janky, though partially due to the curried syntax and all the bizarre indentation rules in the language. The lack of proper .NET Core support is also ridiculous. F# Interactive is weak sauce.

And yeah, C# is catching up. I know it’s superficial, but most of the time these days, C# just requires fewer keystrokes for most things these days.

2018-02-06 - LuigiMX