From C# to F# and Thinking Functionally in C#
Have you ever used a pair of scissors instead of a hair clipper to shave? Ever estimated, the length of “my arm is about 50 cm long, so that’s about two arm-lengths?”
There is elegance in using the right tool for a job. And, just like a hair clipper or a measuring tape, programming languages are tools, and using the right programming paradigm for solving a specified set of problems determines a solution’s effectiveness.
Ralf Herbrich from Microsoft Research had over 1,000 lines of C# code for an application that attempted to analyze millions of feedbacks from users, and on a standard desktop, it took forever…well almost…to process the millions of input data. He rewrote the application in F# within 2 days and the results were astonishing! Less than 10 minutes and the millions of input data items were already processed, and it took only 100 lines of code including comments!
Ralf could also process over 10,000 log lines per second, in an application that parsed over 11,000 text files stored in over 300 directories, importing the data into an SQL database, all in 90 lines of F# code written within just hours!
…and this was way back before the F# language platform had matured fully!
Fig 1.1: Evolution of Programming Paradigms
So what is it about F# and functional programming that makes it a vital programming paradigm for business applications?
Explore with me in this and consecutive weekly blog series, on why F#, or at least its functional way is set to take over normal development from C# and will be a must-have a skill for every quality, time and performance conscious.Net developer and/or respective teams.
Functional Programming already lies at the heart of dominant programming frameworks including:
• React [avoiding shared mutable DOM is the motivation for its architecture],
• AngularJS [RxJS is a library of utility operators that act on streams by way of higher-order functions],
• Redux and ngrx/store and more.
Functional programming today is a close-kept secret amongst researchers, hackers, and elite programmers. Most recently, functional programming is part of the rise of declarative programming models, especially in the data query, concurrent, reactive, and parallel programming domains.
The academic and mathematical origins of functional programming scares an average programmer with words like type inference, closures, currying, continuations, monads, impredicative higher-ranked types, etc, but in these blog series, I will be dispelling demystifying their widely perceived complexity, explaining the concepts in a way mere mortals should understand.
This blog series is about showing you how easy and more effective it is to use the F# as a general purpose tool, and its applicability with an emphasis on the specific problem domains where it can lead to boosts in productivity.
Throughout this blog series, you will discover that whilst F# isn’t the best tool for every situation, it is the perfect tool for many situations. Along the way, you will develop a knack for functional programming, with collections of concepts that will help you rethink and improve your programs regardless of your current programming language.
A Brief Comparison With Other Functional Languages
F# shares a core language with OCaml programming language, and in some ways can be considered an “OCaml for.NET.” It also draws from Haskell’s advanced features called sequence expressions and workflows. Despite similarities to OCaml and Haskell, F# is quite different, in particular, its approach to type inference, object-oriented programming, and dynamic language techniques, is considerably different from all other mainstream functional languages.
F# embraces .NET techniques such as dynamic loading, dynamic typing, and reflection, and it adds techniques such as expression quotation and active patterns.
F# is unique amongst both imperative and declarative languages in that it is the middle road where these two extremes converge. It takes the best features of both paradigms and combines them into an elegant language that both scientists and developers identify with.
F# differs from many functional languages in that it embraces imperative and object-oriented programming. It also provides a missing link between compiled and dynamic languages, combining the idioms and programming styles typical of dynamic languages with the performance and robustness of a compiled language.
Why Functional Programming and F#
F# encourages a different way of thinking about programs. It is based on the powerful principle that behaviour is strictly determined by input so that the same input will always produce the same behaviour. One of F#’s greatest strengths is that you can use multiple paradigms (OO, Imperative, Declarative) and mix them to solve problems in the way you find most convenient, but unlike other paradigms, it allows no side effects. We could argue that since an imperative program is often 90 percent assignment, and a pure functional F# program has no assignment, it could be 90 percent shorter, and more modular.
To see its advantages clearer, we must look at what F# permits rather than what it prohibits. For example, it allows us to treat functions themselves as values and pass them to other functions. This might not seem all that important at first glance, but its implications are extraordinary. Eliminating the distinction between data and function means that many problems can be more naturally solved. In addition to treating functions as values, F# offers other features that borrow from mathematics and are not commonly found in imperative languages.
For example, F# offers curried functions, where arguments can be passed to a function one at a time and, if all arguments are not given, the result is a residual function waiting for the rest of its parameters. It also offers type systems with much better power-to-weight ratios, providing more performance and correctness for less effort.
“The functional programmer sounds rather like a medieval monk, denying himself the pleasures of life in the hope that it will make him virtuous.”
Herewith some virtues we will come across in using F#
Common programming tasks are much simpler in F#, examples being creating and using complex type definitions, list processing, comparison and equality, state machines, and more.
Because functions are treated as first-class objects, it is very easy to create powerful and reusable code by creating functions that have other functions as parameters or combine existing functions to create new functionality.
F# has a more powerful type system that prevents many common errors such as null reference exceptions, values are immutable by default, and that prevents a host of errors. We can encode business logic using the type system itself in such a way that it is actually impossible to write incorrect code or mix up units of measure, relegating unit tests as just a matter of formality, as their need is greatly reduced.
F# is not cluttered with unnecessary coding “noise” such as curly braces, semicolons, and more. You never have to specify an object type, due to a powerful type inference system, and compared with C#, it will always take fewer lines of code to solve the same problem, making maintenance less of a nightmare.
Asynchronous programming is very easy, as is parallelism with its inbuilt libraries. F# also has a built-in actor model, excellent support for event handling and functional reactive programming. Because data structures are immutable by default, sharing state and avoiding locks is way much easier.
Although it is a functional language at heart, F# does support other styles which are not 100% pure, which makes it much easier to interact with the non-pure world of websites, databases, and other applications. In particular, F# is designed as a hybrid functional/OO language, so it can also do everything that C# can do. Obviously, F# is still part of the .Net ecosystem, with seamless access to all third party .NET libraries and tools. It runs on most platforms, including Linux, Android, and IOS (via Mono).
A Trivial code example to whet our appetite:
Let’s try to sum up all the squares from 1 to a specified number N using C# at first and then F#
C# ‘Normal’ Implementation:
We will not dissect the code at this stage, but the example should be enough to immediately show some benefits gained e.g. in conciseness.
When you start to think functionally, you will be able to improve your code in even C# and for the same above code you will implement it as follows:
C# ‘Functional’ Implementation:
Still, we can see that F# wins even against C# as functional, and be rest assured, it wins in many vital scenarios, to be explored in the next series of blogs.
We will explore “how to think functionally,” which is very different from thinking imperatively and will gracefully introduce the functional concepts below with gradually relevant code examples on how they can improve even your C# based solution designs.
• Partial application
• First-class functions
• Higher-order functions
• Function pipelines
• Function composition
• Map, filter, and reduce
• Continuation passing style
• Monads (computation expressions)
These are very important building blocks that will make your functional programming journey very easy when fully understood. Consecutive weekly blogs will dissect every concept individually, and if you are itching to see more code examples, that would be the right time to get our hands dirty.
Author: Kenneth Fukizi – Lead Analyst Consultant