Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# Options... do they really prevent Null Reference Exceptions

Tags:

f#

I am reading the book "Professional F# 2.0" The author shows the following code

let a string : option = None
if a.IsNone then
    System.Console.WriteLine("a is none")
else
    System.Console.WriteLine("a is some");;

then says

"this makes the use of Option vastly superior to the use of null and goes a long way towards removing a significant source of exceptions thrown at runtime"

ok. so I write

System.Console.WriteLine(a.GetType());;

And I get

System.NullReferenceException: Object reference not set to an instance of an object. at System.Object.GetType() at .$FSI_0008.main@() Stopped due to error

And I am like 'un!!!"

How is really doing a

if a.isSome then
    do bla bla

any different from

if a != null then
   do bla bla

So I don't see how is the programmer being saved from NullPointers

PS: NullPointerException has caused me lot of grief in the past.

like image 306
Knows Not Much Avatar asked Jul 04 '12 13:07

Knows Not Much


2 Answers

The F# compiler does not prevent you from NullReferenceException completely. When you work with types defined in .NET, then you can still get null value, because there is no way F# could prevent that.

However, when you work with types declared in F#, then the compiler does not allow creating null values of that type, and so it avoids NullReferenceException in that case. For example, the following code does not compile:

type Person(name:string) = 
  member x.Name = name

// 'Person' is a type declared in F#, so the argument cannot be 'null' in safe code
let printName (person:Person) = 
  printfn "%s" person.Name

// Compiler error here - 'null' is not a valid value of 'Pereson' type
printName null

When you use option<Person> as an argument, then you have to explicitly check for None and Some cases. This is best done using match, which checks that you're not missing any of the cases. For example:

let printName (person:option<Person>) = 
  match person with
  // You get a warning here, saying that you're not handling the 'None' case!
  | Some person -> printfn "%s" person.Name

The warning tells you that you should add case handling None. You can still compile the code, but you will not get NullReferenceException when working with F# types if you do not ignore warnings.

See also this great, related StackOverflow post.

like image 180
Tomas Petricek Avatar answered Oct 02 '22 18:10

Tomas Petricek


To add to the answer by Tomas, a major benefit of Option type lies in the higher order functions that it supports, that give you more brevity and safety. You might find my blog post on the topic useful.

like image 34
missingfaktor Avatar answered Oct 02 '22 18:10

missingfaktor