First of all, NULL is not allowed value for F# type. This is good in some sense and consequently brings trouble.
The first requirement might be: forget about all the argument about option and NULL, I need NULL, that's the way I program. Fine. You can use [< AllowNullLiteral >] attribute on the type you allow it to be NULL.
Some people really into F# will agree about using option is a better choice. However, this restriction makes F# program difficult to communicate with C# program. For example, you want to use F# library from C#. Can you really forbidden C# user set NULL value into your perfect world? Or Should you? Instead of being a coding police and forcing everyone, I would like to keep my world clean and let others to continue their way. I will use a property to filter the incoming NULL to a option value, expose NULL value to outside world, and, in the meanwhile, protected my inside world from being contaminated by NULL.
The following code use the Unchecked.default function. Unfortunately, the match won't work very well in the setter function, so I just use if...else.
type A() =
let mutable a:option< A > = None
with get() =
match a with
| Some(n) -> n
| None -> Unchecked.defaultof< A >
and set(v) =
if v = Unchecked.defaultof< A > then a <- None
else a <- Some(v)
In this way, I can keep NULL from my code and still provide a nice C# experience to C# users.
if you really need to check the NULL value in the F# code, you can always use box(yourValue) and then it is OK to do box(yourValue) = null.
Please remove some space if the code does not compile, the blog editor does not work very well with F# code.. :(