Option and ValueOption
Use Option instead of null for "may be missing". It forces callers to handle the absent case.
// type Option<'T> = Some of 'T | None
let tryDivide x y = if y = 0 then None else Some (x / y)
tryDivide 10 2 // Some 5
tryDivide 10 0 // None
match tryDivide 10 0 with
| Some v -> printfn "Result %d" v
| None -> printfn "Cannot divide by zero"
// Option module
Some 5 |> Option.map (fun x -> x * 2) // Some 10
None |> Option.map (fun x -> x * 2) // None
Some 5 |> Option.bind (fun x -> tryDivide 100 x) // Some 20
Some 5 |> Option.defaultValue 0 // 5
None |> Option.defaultValue 0 // 0
Some 5 |> Option.filter (fun x -> x > 10) // None
Option.isSome (Some 1), Option.isNone None // true, true
Some 3 |> Option.iter (printfn "got %d")
Option.ofObj (null: string) // None: convert nullable .NET values
Option.ofNullable (System.Nullable 5) // Some 5
Some "x" |> Option.toList // ["x"]
[ Some 1; None; Some 3 ] |> List.choose id // [1; 3]
Option.orElse (Some 2) None // Some 2
// Chaining with a computation expression (FsToolkit.ErrorHandling, or a custom builder; Module 31)
// option { let! a = tryDivide 100
…