I'm aware that they both use different programming paradigms, but from a high level perspective apart from differing syntax it seems most basic tasks can be achieved in similar fashion.
I only say this because when I've previously touched functional programming languages such as Haskell, writing code for basics tasks was (at first) difficult, frustrating, and required a completely different mindset.
For example the following took some time to get to grips with using recursive syntax:
loop :: Int -> IO ()
loop n = if 0 == n then return () else loop (n-1)
Where as an F# loop is recognisable and understandable almost immediately:
let list1 = [ 1; 5; 100; 450; 788 ]
for i in list1 do
printfn "%d" i
When C# programmers start learning F# they are advised to completely re-think their thought pattern (which was definitely required for Haskell), but I've now written several F# programs dealing with conditions, loops, data sets etc to perform practical tasks, and I'm wondering where the 'different-paradigm' barrier really kicks in?
Best Answer
F# supports Object Oriented Programming but OOP isn't really idiomatic F#. OOP encourages bundling of data and behavior while functional programming encourages separating them.
Take a look at the difference between the
System.Collections.Generic.List<T>
andMicrosoft.FSharp.Collections.List<'T>
classes.The regular (OOP) class has a large list of methods and extension methods for example,
List<T>.Add(T)
. In contrast, the F# list has only a few properties while all of the related functions are grouped into a List module.Let's looks at a familiar OOP example:
You could translate that to F# (non-idiomatic):
You can see that the code is shorter but not really any different. If you find yourself writing code like this, you're thinking like a C# dev :) Here's a more idiomatic translation:
Here's a alternative version of
speak
:At this point, the code looks very different than the C# version largely because we have separated the behavior (
speak
orSpeak()
) from the data (in this case, just the type ofAnimal
orIAnimal
we have). One other difference is that we have expressed the possible states of data (animal kinds) in a way the compiler (and type-system) understand more intimately than the C# compiler/typesystem. Consider a function which gets the first item in a list:vs:
Both take a idiomatic list and return the first item in it (
::
is the list destructuring operator).If you were to compile both of these, the C# version would compile with no errors or warnings and the F# version would warn you that you haven't considered all of the cases (what about the empty list?). The F# compiler realizes you haven't accounted for all possible inputs and warns you accordingly.
This is one of the other differences between the languages, as a programmer (if you have idiomatic code), you can lean on the compiler a lot more for detecting errors and bugs which C#/OOP wouldn't catch until runtime.