6 things you should know before starting learning F#
When you’re starting learning F# after C# (or other object-oriented language) some language constructs and ideas may seem… weird or counter intuitive. In wanted to briefly mention these things, so you could save some time with compiler trying to understand what you’re doing wrong.
1. Syntax
When you compare C#, Java, Javascript most of things look similar – we got braces, pretty much same types, classes. F# on the other hand was created a little bit different – first of all there are no braces and similar to python function/class scope is achived using indents. Because of that F# is much more concise in comparing to C# (check yourself).
Next thing – function declararion syntax. We got strong typing languages like C# and weak typing like javascript. F# tries (and in most cases succeed) trying to merge this two approaches – underneath its strong typing, but compiler by context understand what type is used and lets you not write it strict declaration of it. Because of that in many cases function signature is quite simple
let func1 arg1 arg2 arg3 = //function body
but in some cases, when you need to pass the type it gets… awkward:
let func1 (arg1:int) arg2 (arg3:list int) = //function body
But on the bright side F# allows to write language contstruct names as whole sentences
let <code></code>long function name with spaces<code></code> arg1 arg2 arg3 = //function body
which is especially useful for writing unit tests.
2. Order matters
F# definitely hate cyclic dependencies. That’s why they created some restrictions that strictly forbids you from creating this kind of dependencies. First – files order in solution does matter – to use stuff from file A in file B, A must be before B in solution explorer window. That’s why we have these weird options in context menu – to order files around:
Order inside file also matters, but we have a more flexibility – we have and keyword to create two types that depend on each other.
3. Advanced math and monads
Functional programming itself is a children of a part of mathematics called “Category theory” which describes functions and types. So inclination towards mathematics and mathematical jargon are typical. Does these mean when you start learning F# you have to already know terms like monad or endofunctor? Well in time, you’ll for sure start to use them, because they can simplify a lot of your code, but you don’t have to know what they’re from the beginning. With time you’ll understand even this famous quote:
Monads are just monoids in the category of endofunctors
4. Null handling
Null references are often described as a bilion dollar mistake, even by its creator. Even thought null checking is one of the most common things you can encounter in any source code, NullReferenceException is still very common in all applications. Why not eliminate it althogheter with nulls? There is a move in modern languages to limit possiblity of nulls (Swift, C# 7) and also in F# nulls can be used only if you specificly state that, by default all structures are non-nullable. Nulls are possible to use in F# for compatibility with .Net framework reasons and you should use them only for that. So whats instead of them? Discriminated unions, especially:
type Option<'a> = | Some of 'a | None
Option type has two possible values Some of generic type or None so to access boxed type you have strictly check if there is some value i.e. using pattern matching.
5. Immutability
By default all data in F# is immutable – it means you initialize it and then to change it you have to create new object. Just like strings in C#. Because of that we don’t have to worry about whole set of problems cause by – why is this field changing? You can of course create mutable field/value using mutable keyword, but you should do this only in corner cases.
6. fs, fsi, fsx files
When you add new file you have the option to choose one of three fs, fsi and fsx. What’s the difference between them? In 95% you’ll choose fs – its standard F# file. Sometimes you want to create F# script run in interactive window – you can do that using fsx files. And in the end fsi – there are signature files used only in libraries – details.