Shades of F#

Explore F# programming through different perspectives: functional vs. imperative approaches. Discover design patterns, learning resources, and practical insights.

6 min read 1,177 words

I am writing after a long time about F#. And this would be a little bit controversial post. Take it with a pinch of salt.

Recently I got a call from a company that wanted me to do some work in F# for its client. The client took my interview and told me that its client wants to do some work in F#. Things were going smoothly until the interviewer asked me if I should be writing F# code following standard design patterns.

I just went into pause mode, as my brain was trying to search for Functional Programming Design Patterns. It gave me Scott Wlaschin's famous answer: In functional programming, every design pattern is a function. But I couldn't give that answer to the client's operator for sure. So, I gave the other best possible answer.

You are asking about F# code like Python or F# code like Haskell?

The contract didn't get converted but this post does.

Let's start with the first shade: F# like typed Python.

If you are old enough to know and write code with Visual Studio 2012, then go back to that time and try to remember good talks you have seen to learn F#.

Here are a few of my favorites:

There are common things you can abstract away from it:

  • Functions (obviously)
  • Forward Pipe (Best thing in the language)
  • Type Providers

There were no Result Type, Elevated world, not even Railways. Even I had to ask on Stack Overflow just to do multiple validations on an entity.

The language was so simple and beautiful. The tooling was good enough—at least it worked most of the time. It didn't crash on my lap just because I had opened any big project. People were way more friendly back then compared to now for sure. Good old days.

Python gets traction from the Data Science community because of its simplicity. It is too good for writing algorithms, especially when you have definite input and output.

Here, F# just adds more power to this. You have types and type providers, you can write simple functions to process data, and join them using forward pipes. It was too much fun back then—I tend to convert every damn thing to forward pipe. Overdoing it sometimes, but it was fun. This is the F# I loved the most. I still like this kind of programming: no specific types, a few record types to define input and output, and all the functions. Files and modules are always there to help in case of separation. So nice and so Python-like.

Let's see some code. I am demoing the famous World Bank data example (from their docs only).

{{<gist kunjee17 48b191951311fd2fc828e7ca0e290c95>}}

So, what's wrong with this approach? Practically nothing, but real-world problems (especially in web, distributed systems, mobile, etc.) kind of need something more. They need more design and architecture to hold big applications together.

But don't we already have design patterns for ages? Can't they be applied to F#?

F# is a functional-first language running on .Net, and it does support object-oriented programming. Here comes the second shade of F#.

F# as better C#.

If someone like me is coming from C#, this might be a natural transition. Try to map whatever you learn in C# to F#. I also wrote a couple of articles back then explaining how you can use traditional object-oriented design patterns in F#.

Here is how a typical C# class looks like:

{{}}

and here is the equivalent beautiful F# code:

{{}}

You can make it a little bit terser without going more functional:

{{}}

Look how beautiful F# code looks. I did write immutable C# code so I don't have to write mutable F# code.

Let's push F# code to a little more functional end. Here we have a small example from Railway Oriented Programming.

We are defining a kind of domain with two different styles:

{{<gist kunjee17 10c6b6c6f58458639994cfa881b867a5>}}

Let's do the same thing with a class:

{{<gist kunjee17 53f4bb25350cb9d6879be0ef699e5839>}}

Pick your choice—both give almost the same result on the consumer side.

But with this, we are moving more towards Haskell. Languages like Haskell and Scala have something called HKT or Higher Kind Types backed into the language.

F# as a language by design lacks features like HKT.

For a long time I didn't know that HKT means Higher Kind Types. And it took me an even longer amount of time to understand it.

There is a discussion going on about how useful it is. So it depends on the choice of elders, but F# at the time of writing this blog doesn't have HKT.

It still doesn't stop anyone from pushing their F# code more towards Haskell.

Here is the final shade: F# more like Haskell.

If you like to skip all the IO and monad stuff, just pause this blog here and watch this video by Scott W.

You can gradually grow your system to push towards Haskell. A little help to LIFT your code will surely be useful. Read Functional Programming for Fun and Profit's Railway oriented programming post, written by Scott Wlaschin.

Or you can use a wonderful library like F# plus.

Let's check out the validation example I have taken from the docs of F# plus. You can build upon that.

{{<gist kunjee17 7c306d989a14b8ae665a8e577970890e>}}

This style of coding is very helpful when you are designing a big IO-based system. This way you easily separate logic from execution.

I did purposefully skip heavy functional concepts here—concepts and patterns based on Algebra, Category Theory, Monads, etc. It's good and important to know them, but that is totally out of scope for this blog. So, maybe next time.

F# is a very flexible language, and one can bend it as one likes. Write down in the comments what is your shade of F#?

Frequently Asked Questions

What are the different shades of F# programming?

F# can be written in different styles depending on the approach. One shade is 'F# like typed Python,' which uses functional programming concepts but in a more pragmatic, accessible way similar to Python's syntax and simplicity. Another shade is 'F# like Haskell,' which follows pure functional programming principles more strictly. The choice depends on your project needs and team familiarity.

Do I need to follow design patterns when writing F# code?

In functional programming, the traditional object-oriented design patterns work differently in F#. As Scott Wlaschin famously said, 'In functional programming, every design pattern is a function.' Instead of traditional design patterns, F# emphasizes using functions and functional composition as the primary way to solve architectural problems.

What are the key features of F# that make it powerful?

F# has several powerful features including first-class functions, the forward pipe operator (|>) for readable code composition, and type providers for compile-time type safety. The language is simple and beautiful, allowing you to write clean, expressive code while maintaining strong type safety without excessive verbosity.

Is F# suitable for practical applications like machine learning and game development?

Yes, F# is highly suitable for practical applications. It's been successfully used for machine learning research (as demonstrated by Evelina Gabasova), game development with high performance, mobile app development with Xamarin, and parallel/asynchronous programming. F# proves that functional programming doesn't sacrifice performance or real-world applicability.

Share this article