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?

  • 8
    Another question is whether your F# example represents idiomatic F#, or if a functional programmer would write that for loop differently, such as list1.iter (printfn "%d"). (Just as an example; I'm not even sure if that would compile. :) – stakx Aug 24 '13 at 12:56
  • 4
    Have you looked here? – Aaron McIver Aug 24 '13 at 12:57
  • ADTs and pattern matching should be the biggest paradigm shift (and I'm still puzzled why such a basic tool have not been added to C#). All the functional mumbo-jumbo is irrelevant nowadays since it's already present and widely used in C#. – SK-logic Aug 27 '13 at 15:39

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> and Microsoft.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:

public interface IAnimal
    void Speak();

public class Duck : IAnimal
    public void Speak()

public class Cat : IAnimal 
    public void Speak()

You could translate that to F# (non-idiomatic):

type IAnimal = 
    abstract member Speak : unit -> unit

type Duck = 
    interface IAnimal with
        member this.Speak () -> printfn "Quack!"

type Cat = 
    interface IAnimal with
        member this.Speak () -> printfn "Meow!"

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:

type Animal = 
    | Duck
    | Cat

let speak animal = 
    match animal with 
    | Duck -> printfn "Quack!"
    | Cat -> printfn "Meow!"

Here's a alternative version of speak:

let speak = function
    | Duck -> printfn "Quack!"
    | Cat -> printfn "Meow!"

At this point, the code looks very different than the C# version largely because we have separated the behavior (speak or Speak()) from the data (in this case, just the type of Animal or IAnimal 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:

public T GetHead(List<T> list)
    return list[0];


let getHead = function
    | head :: tail -> head

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.


I'm wondering where the 'different-paradigm' barrier really kicks in?

There largely is no "barrier". You're free to write non-idiomatic F# all you want - just like you could program C# for ages and not really practice object oriented programming.

The only case I can really see forcing your hand is working with other developers. You'll see their style with the language and will have to adapt to using it. More importantly, they'll not stand for you writing loops in a functional codebase.

  • 6
    +1 this is why I always suggest Haskell for people who genuinely want to get the benefit of learning a functional language, F# and some lisps and a variety of functional languages will let you do exactly what you're already doing in other languages; and learn nothing, which people tend to come away with the lesson that "Oh, it's basically the same". F# as you said, has no barrier. It's C# with some added bells and whistles, but learning FP often won't happen until you need to do two actions in a row, and you can't just write them one line after the other. – Jimmy Hoffa Aug 26 '13 at 1:09
  • @JimmyHoffa - I completely agree, and also recommend Haskell for the same reason. – Telastyn Aug 27 '13 at 14:44

F# is a hybrid language: it's primarily a functional language, but it can also do pretty much everything C# can do. So, you can use mutable variables, mutable collections, methods with side-effects and inheritance hierarchies everywhere. But if you do that, you will find that F# is not a very good imperative language and it would have been better if you stayed with C#.

On the other hand, if you want to write idiomatic F#, you will need to learn how to use immutable variables, immutable collections, pure functions, discriminated unions and pattern matching.

To sum up, if you really want to take advantage of what F# can offer, you will indeed need to re-think how you code, though probably not as radically as is required for Haskell.

  • I am in <3 with Discriminated Unions and Pattern matching. However, when I first saw them I thought 'clever enums' or 'structs with inheritance' and better switch syntax. This was a bump, because they are definitely no that! – CodeBeard Aug 24 '13 at 19:42

I will comment from experience of using both languages (C# and F#) and the 'bumps' I have found. (I would agree that there are no barriers. There are definitely 'bumps' in the road though).

I first used F# for scripting through fsi because you can't do that with C# and I had been learning some functional paradigm stuff. F# did a really good, concise job because the task at hand was suited to functional programming (it was essentially map/reduce).

The biggest bump was in 'forgetting' objects, and realising that I don't have to use loops and conditionals. I spent a lot of time in this 'scripting' space. (I looked back at some old F# and saw how I was trying to 'force it' in the past).

I am now doing my first big piece of work in F# - a DSL. It is a better suited language for this task. I still use C# - this is my 'systems' language. Objects moving around and mutability suits the mental model I have of how that works.

I would say that it is about best fit for the job rather than making a total switch. The massive benefit is that it makes you think differently about how to solve various problems. Since I have learnt F# my C# has massively improved.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.