I posted a question to StackOverflow yesterday and will describe the issue and resolution in this post.
F# is a funny language in that it is a functional (I suppose it's multi-paradigm but very strong emphasis on functional) language built on the .NET platform which has a very different style as a whole. I had an interesting issue the other day where I noticed a
null value at runtime being returned from a .NET component in a place that F# was certain
null values could not exist.
In my case this was Entity Framework. I followed this walkthrough to create F# types that mapped to my database using Entity Framework Code First. I wrote a query that ended in .FirstOrDefault() and here is where the problem started:
let result = context .SearchResults .Where((fun (r:SearchResult) -> r.Program = request.Program)) .OrderByDescending((fun r -> r.AcquisitionDate)) .FirstOrDefault()
.FirstOrDefault() is implemented such that it returns either the first element if one exists, or
default(T) if not. Well my
SearchResult type is defined in F# and is just a regular class so the
default(typeof(SearchResult)) is equal to
null. However, F# doesn't allow nulls be default - due to its functional nature it doesn't by default support
null values (which I've come to really appreciate when I'm writing 'pure' F#). So when the database has no data, what value do you think is bound to
If you guessed
null you were right. But I just said that F# doesn't support
null. So the following code does not compile:
match result with | null -> () // do nothing since this doesn't compile anyway | price -> () // do nothing since this doesn't compile anyway
the compilation error states
the type 'SearchResult' does not have 'null' as a proper value
Interesting. So SearchResult doesn't support
null. Even more interesting is if you comment out the bad code and run it you'll see that
result which is of type
SearchResult is indeed bound to
It seems to me that in a world of uncertainty – a world of mixed paradigms - F# assumes a convention. F# assumes that every component is as functionally pure as it is - though it is made to interoperate with components that are known not to be.
It turns out that the fix to this is pretty simple. As stated in the first paragraph in the MSDN article on nulls in F#, F# has an
AllowNullLiteral attribute. I decorated my EF types with this and then the compiler allowed me to compare my
results value to
null. How imperative!