Mark Needham

Thoughts on Software Development

F# Option Types

with 6 comments

I’ve been spending a bit of time working through the Real World Functional Programming book to learn a bit about F# and one of the cool features I came across today (while reading Chris Smith’s post on F# lists) is the Option type.

I first came across this idea a few months ago when discussing null handling strategies with a colleague who pointed out that you could get around this problem in Scala by using the Option class.

From what I can tell this works pretty much the same way and solves the problem that we have when we want to perform an operation but don’t know whether or not a value will be returned.

If a value is returned then we don’t have a problem, but if not then we want a clean way of handling this.

One example of this is when trying to retrieve a value from a collection. When we try to get a value which doesn’t exist this would typically throw an exception.

To give an F# example, trying to find the value 7 in a list from 1-5:

List.find (fun x -> x = 7) [1..5];;

This throws the following exception:

System.Collections.Generic.KeyNotFoundException: The item was not found in the collection
   at Microsoft.FSharp.Core.Operators.not_found[T]()
   at <StartupCode$FSI_0277>.$FSI_0277._main()

Luckily there is another way of trying to find this value:

List.tryfind (fun x -> x = 7) [1..5];;
val it : int option = None

Note that the type is now ‘int option’ with a value of ‘None’. If we search for a value that does exist:

List.tryfind (fun x -> x = 3) [1..5];;
val it : int option = Some 3

We get a return value of ‘Some 3’.

The beauty of this approach comes when pattern matching against these values. To give a contrived example:

let find value list =
    let option = List.tryfind(fun item -> item = value) list
    match option with
    | None -> printfn "Value %d not found" value
    | Some(valueFound) -> printfn "Found value: %d" valueFound;;
> find 1 [1..5];;
Found value: 1
val it : unit = ()
> find 6 [1..5];;
Value 6 not found
val it : unit = ()

I really like this idea and it seems cleaner than approaches I have used in C# and Java to achieve a similar outcome. I’m sure I’ll come across more usages for it as my knowledge of F# increases.

Incidentally, Luis Diego Fallas has written a cool post showing how to use option types in C#. The syntax obviously isn’t quite as clean as it is in F# but it still reads reasonably nicely.

Be Sociable, Share!

Written by Mark Needham

January 2nd, 2009 at 10:35 pm

Posted in .NET,F#

Tagged with , ,

  • I’ve been a big fan of using the option type instead of null for quite a while now. To me although it’s just a small change, it really does lead to cleaner, safer code. I talk some more about how it can be used in this blog post:

  • Pingback: » Blog Archive » ML-style Pattern Matching in C#()

  • Pingback: Real World Functional Programming: Book Review at Mark Needham()

  • Alex O.

    I am new to F# and like what I see so far.
    But I’d like to voice some dissent on this issue though: while the Option type helps to avoid the exception in this case, it still requires the use of a dedicated try… function, so in the end it’s still the programmer’s responsibility to account for a possible nullable result of an operation. In other words, this safer result handling does not come “for free” from the language.
    So, my question: how is it fundamentally better than, say, nullable types in C# or similar functions in .NET in general (e.g. Int32.TryParse())?

    Just trying to learn, that’s all.

  • @Alex I think if it’s just single values that we care about (as in my example) then the main benefit for me is that you’re explicitly saying that the value might have a value but it might not – I guess maybe this is the same as with the nullable type in C#.

    If you’re doing something like iterating over a list which has Options in it then your ability to do pattern matching is much improved since you can easily distinguish between whether you are dealing with something which has a value and something which doesn’t. It wouldn’t be so easy if you had to distinguish between null and not null from what I understand.

  • Pingback: Reading Code: Unity at Mark Needham()