2 people like it.
Like the snippet!
Reimplementation of C# Nullable type
Type-safe Nullable in F# featuring:
arithmetic operations on primitive types,
structural equality/comparison,
null-coalescing operator,
explicit type conversion to the underlying type,
throwing an exception in exceptional condition,
`nullable` computation expression,
and etc.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
|
// XXX Uncomment the following two lines:
//[<StructuralEquality; StructuralComparison>]
//[<Struct>]
type FSharpNullable<'T when 'T : struct> =
| Value of 'T
| Null
module FSharpNullable =
let bind f x =
match x with
| Null -> Null
| Value x' -> f x'
type FSharpNullableBuilder() =
member __.Bind(x, f) = x |> FSharpNullable.bind f
member __.Return(x) = Value x
[<AutoOpen>]
module FSharpNullableOps =
let nullable = FSharpNullableBuilder()
let inline ( .+. ) (a: FSharpNullable<'T>) (b: FSharpNullable<'T>) : FSharpNullable<'T> =
nullable {
let! x = a
let! y = b
return x + y
}
let inline ( .+ ) (a: FSharpNullable<'T>) (b: 'T) : FSharpNullable<'T> =
nullable {
let! x = a
return x + b
}
let inline ( +. ) (a: 'T) (b: FSharpNullable<'T>) : FSharpNullable<'T> =
nullable {
let! y = b
return a + y
}
let inline ( .-. ) (a: FSharpNullable<'T>) (b: FSharpNullable<'T>) : FSharpNullable<'T> =
nullable {
let! x = a
let! y = b
return x - y
}
let inline ( .- ) (a: FSharpNullable<'T>) (b: 'T) : FSharpNullable<'T> =
nullable {
let! x = a
return x - b
}
let inline ( -. ) (a: 'T) (b: FSharpNullable<'T>) : FSharpNullable<'T> =
nullable {
let! y = b
return a - y
}
let inline ( .*. ) (a: FSharpNullable<'T>) (b: FSharpNullable<'T>) : FSharpNullable<'T> =
nullable {
let! x = a
let! y = b
return x * y
}
let inline ( .* ) (a: FSharpNullable<'T>) (b: 'T) : FSharpNullable<'T> =
nullable {
let! x = a
return x * b
}
let inline ( *. ) (a: 'T) (b: FSharpNullable<'T>) : FSharpNullable<'T> =
nullable {
let! y = b
return a * y
}
let inline ( ./. ) (a: FSharpNullable<'T>) (b: FSharpNullable<'T>) : FSharpNullable<'T> =
nullable {
let! x = a
let! y = b
return x / y
}
let inline ( ./ ) (a: FSharpNullable<'T>) (b: 'T) : FSharpNullable<'T> =
nullable {
let! x = a
return x / b
}
let inline ( /. ) (a: 'T) (b: FSharpNullable<'T>) : FSharpNullable<'T> =
nullable {
let! y = b
return a / y
}
type FSharpNullable<'T when 'T : struct> with
member this.Bind(f) = this |> FSharpNullable.bind f
member this.HasValue =
match this with
| Null -> false
| Value _ -> true
static member inline op_Explicit(this) : 'T =
match this with
| Null -> raise <| System.InvalidOperationException(
"Nullable object must have a value.")
| Value x -> x
static member inline ( <??> ) (lhs, rhs) =
match lhs with
| Null -> rhs
| Value x -> x
static member inline (+) (a, b) = a .+. b
static member inline (-) (a, b) = a .-. b
static member inline (*) (a, b) = a .*. b
static member inline (/) (a, b) = a ./. b
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
|
let a = Value 19 + Value 23 // val a : FSharpNullable<int> = Value 42
let b = Value 13 .+. Value 29 // val b : FSharpNullable<int> = Value 42
a = b // val it : bool = true
let c = a .+ 42 // val c : FSharpNullable<int> = Value 84
let n = a + Null // val n : FSharpNullable<int> = Null
a + c <??> 42 // val it : int = 126
a + c + n <??> 42 // val it : int = 42
int a // val it : int = 42
int64 a // error FS0001: The type 'FSharpNullable<int>' does not support a conversion to the type 'int64'
int64 (Value 42L) // val it : int64 = 42L
int n // System.InvalidOperationException: Nullable object must have a value.
|
union case FSharpNullable.Value: 'T -> FSharpNullable<'T>
union case FSharpNullable.Null: FSharpNullable<'T>
type FSharpNullable<'T (requires value type)> =
| Value of 'T
| Null
member Bind : f:('T -> FSharpNullable<'a>) -> FSharpNullable<'a> (requires value type)
member HasValue : bool
static member ( + ) : a:FSharpNullable<'a> * b:FSharpNullable<'a> -> FSharpNullable<'a> (requires value type and member ( + ))
static member ( / ) : a:FSharpNullable<'a> * b:FSharpNullable<'a> -> FSharpNullable<'a> (requires value type and member ( / ))
static member op_Explicit : this:FSharpNullable<'T> -> 'T
static member ( <??> ) : lhs:FSharpNullable<'a> * rhs:'a -> 'a (requires value type)
static member ( * ) : a:FSharpNullable<'a> * b:FSharpNullable<'a> -> FSharpNullable<'a> (requires value type and member ( * ))
static member ( - ) : a:FSharpNullable<'a> * b:FSharpNullable<'a> -> FSharpNullable<'a> (requires value type and member ( - ))
Full name: Script.FSharpNullable<_>
val bind : f:('a -> FSharpNullable<'b>) -> x:FSharpNullable<'a> -> FSharpNullable<'b> (requires value type and value type)
Full name: Script.FSharpNullable.bind
val f : ('a -> FSharpNullable<'b>) (requires value type and value type)
val x : FSharpNullable<'a> (requires value type)
val x' : 'a (requires value type)
Multiple items
type FSharpNullableBuilder =
new : unit -> FSharpNullableBuilder
member Bind : x:FSharpNullable<'b> * f:('b -> FSharpNullable<'c>) -> FSharpNullable<'c> (requires value type and value type)
member Return : x:'a -> FSharpNullable<'a> (requires value type)
Full name: Script.FSharpNullableBuilder
--------------------
new : unit -> FSharpNullableBuilder
member FSharpNullableBuilder.Bind : x:FSharpNullable<'b> * f:('b -> FSharpNullable<'c>) -> FSharpNullable<'c> (requires value type and value type)
Full name: Script.FSharpNullableBuilder.Bind
val x : FSharpNullable<'b> (requires value type)
val f : ('b -> FSharpNullable<'c>) (requires value type and value type)
Multiple items
module FSharpNullable
from Script
--------------------
type FSharpNullable<'T (requires value type)> =
| Value of 'T
| Null
member Bind : f:('T -> FSharpNullable<'a>) -> FSharpNullable<'a> (requires value type)
member HasValue : bool
static member ( + ) : a:FSharpNullable<'a> * b:FSharpNullable<'a> -> FSharpNullable<'a> (requires value type and member ( + ))
static member ( / ) : a:FSharpNullable<'a> * b:FSharpNullable<'a> -> FSharpNullable<'a> (requires value type and member ( / ))
static member op_Explicit : this:FSharpNullable<'T> -> 'T
static member ( <??> ) : lhs:FSharpNullable<'a> * rhs:'a -> 'a (requires value type)
static member ( * ) : a:FSharpNullable<'a> * b:FSharpNullable<'a> -> FSharpNullable<'a> (requires value type and member ( * ))
static member ( - ) : a:FSharpNullable<'a> * b:FSharpNullable<'a> -> FSharpNullable<'a> (requires value type and member ( - ))
Full name: Script.FSharpNullable<_>
val __ : FSharpNullableBuilder
member FSharpNullableBuilder.Return : x:'a -> FSharpNullable<'a> (requires value type)
Full name: Script.FSharpNullableBuilder.Return
val x : 'a (requires value type)
Multiple items
type AutoOpenAttribute =
inherit Attribute
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
member Path : string
Full name: Microsoft.FSharp.Core.AutoOpenAttribute
--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
val nullable : FSharpNullableBuilder
Full name: Script.FSharpNullableOps.nullable
val a : FSharpNullable<'T> (requires value type and member ( + ))
val b : FSharpNullable<'T> (requires value type and member ( + ))
val x : 'T (requires value type and member ( + ))
val y : 'T (requires value type and member ( + ))
val b : 'T (requires value type and member ( + ))
val a : 'T (requires value type and member ( + ))
val a : FSharpNullable<'T> (requires value type and member ( - ))
val b : FSharpNullable<'T> (requires value type and member ( - ))
val x : 'T (requires value type and member ( - ))
val y : 'T (requires value type and member ( - ))
val b : 'T (requires value type and member ( - ))
val a : 'T (requires value type and member ( - ))
val a : FSharpNullable<'T> (requires value type and member ( * ))
val b : FSharpNullable<'T> (requires value type and member ( * ))
val x : 'T (requires value type and member ( * ))
val y : 'T (requires value type and member ( * ))
val b : 'T (requires value type and member ( * ))
val a : 'T (requires value type and member ( * ))
val a : FSharpNullable<'T> (requires value type and member ( / ))
val b : FSharpNullable<'T> (requires value type and member ( / ))
val x : 'T (requires value type and member ( / ))
val y : 'T (requires value type and member ( / ))
val b : 'T (requires value type and member ( / ))
val a : 'T (requires value type and member ( / ))
val this : FSharpNullable<'T> (requires value type)
member FSharpNullable.Bind : f:('T -> FSharpNullable<'a>) -> FSharpNullable<'a> (requires value type)
Full name: Script.FSharpNullable`1.Bind
val f : ('T -> FSharpNullable<'a>) (requires value type and value type)
member FSharpNullable.HasValue : bool
Full name: Script.FSharpNullable`1.HasValue
static member FSharpNullable.op_Explicit : this:FSharpNullable<'T> -> 'T
Full name: Script.FSharpNullable`1.op_Explicit
val raise : exn:System.Exception -> 'T
Full name: Microsoft.FSharp.Core.Operators.raise
namespace System
Multiple items
type InvalidOperationException =
inherit SystemException
new : unit -> InvalidOperationException + 2 overloads
Full name: System.InvalidOperationException
--------------------
System.InvalidOperationException() : unit
System.InvalidOperationException(message: string) : unit
System.InvalidOperationException(message: string, innerException: exn) : unit
val x : 'T (requires value type)
val lhs : FSharpNullable<'a> (requires value type)
val rhs : 'a (requires value type)
val a : FSharpNullable<'a> (requires value type and member ( + ))
val b : FSharpNullable<'a> (requires value type and member ( + ))
val a : FSharpNullable<'a> (requires value type and member ( - ))
val b : FSharpNullable<'a> (requires value type and member ( - ))
val a : FSharpNullable<'a> (requires value type and member ( * ))
val b : FSharpNullable<'a> (requires value type and member ( * ))
val a : FSharpNullable<'a> (requires value type and member ( / ))
val b : FSharpNullable<'a> (requires value type and member ( / ))
val a : FSharpNullable<int>
Full name: Script.a
val b : FSharpNullable<int>
Full name: Script.b
val c : FSharpNullable<int>
Full name: Script.c
val n : FSharpNullable<int>
Full name: Script.n
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
Multiple items
val int64 : value:'T -> int64 (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int64
--------------------
type int64 = System.Int64
Full name: Microsoft.FSharp.Core.int64
--------------------
type int64<'Measure> = int64
Full name: Microsoft.FSharp.Core.int64<_>
More information