Shades of F#
Explore F# programming through different perspectives: functional vs. imperative approaches. Discover design patterns, learning resources, and practical insights.
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:
- The Best Introduction to F# by Luca Bolognese, people might point you to many different resources for getting started with F#. But this video is still the best one to get started. Trust me on that.
- "How machine learning helps cancer research" by Amazing Dr. Evelina Gabasova, one of the gifted speakers in the F# and machine learning community. Not only is she a good speaker, but she is also a damn good person, guru, and wonderful friend.
- Parallel and Asynchronous Programming with F# by Father of F# Don Syme. If you still think Don Syme is human, then go watch this video. He is not—you can tell from the way he pulls off this talk and the way he codes.
- Building a Better SQL Type Provider with Ross McKinlay. This guy bent the language to practically a level where the language has to tell him, "Enough is enough, man."
- Game Programming in FSharp with Andrea Magnorsky. I call her and Ross the Dragon Masters. You think FP is slow? Think again. Dragon Master Andrea is going to prove you wrong.
- Xamarin Evolve 2014: Mobile App Development in F# - Rachael Reese, Firefly Logic - Long before Fabulous was born, F# was working with Xamarin. If I remember correctly, Rachael gave the first talk about it.
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
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.
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.
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.
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.