The spec has quite a nice section on nullness:

[link:research.microsoft.com]

In a nutshell, F# still has to deal with null since any framework method could return null. Strings are part of the CLR's BCL so can be null, F#'s native types, such as tuples, records and unions cannot be null, most other types can.

Cheers,

Rob

By on 1/12/2009 4:16 AM ()

The spec has quite a nice section on nullness:

[link:research.microsoft.com]

In a nutshell, F# still has to deal with null since any framework method could return null. Strings are part of the CLR's BCL so can be null, F#'s native types, such as tuples, records and unions cannot be null, most other types can.

Cheers,

Rob

No plans for implementing native strings or char types? I hate when types are nullable by default!

By on 1/13/2009 2:25 PM ()

I hate when types are nullable by default!

Yeh, me too. Actually Spec# has solution for this. They just use special symbol (similar with Nullable<T> - "?").

By on 1/13/2009 2:51 PM ()

Thank you, a bit strange behaviour...

Sorry, but then I have another question.

Is there any way to improve this code

1
2
type Content =
    | Html of string

to restrict Html to be non null?

By on 1/12/2009 4:53 AM ()

Here's an improved version that uses a constructed type where the non-nullable constraint is enforced in the constructor. This is much safer such that any time you have an instance of the NonNull class, you are guaranteed to have a non-null value:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#light

type NonNull<'a>(x : 'a) =
    do if box x = null
        then failwith "null is not a valid value"
    
    member this.Value = x
    
    override this.ToString() = x.ToString()

let (!!) (x : NonNull<'a>) = x.Value

let nn1 = NonNull("a string")
printfn "%A" !!nn1 // "a string"

try
    let nn2 = NonNull(null)
    ()
with ex -> printfn "Error: %s" ex.Message // Error: null is not a valid value

You can use this type with your Union type like so:

1
2
3
4
5
6
7
8
9
10
type Content = 
    | Html of NonNull<string>

let c1 = Html(NonNull("a string"))
printfn "%A" c1 // Html a string

try
    let c2 = Html(NonNull(null))
    ()
with ex -> printfn "Error: %s" ex.Message // Error: null is not a valid value
By on 1/13/2009 5:42 AM ()

Here's an improved version that uses a constructed type....

Thank you very much, but this is common solution for languages with nullable types. For example you can find one of the implementations here - [link:msmvps.com]. Beside noise in syntax it move checks at the runtime, which non-nullable types could overcome.

By on 1/13/2009 2:46 PM ()

You can pretty easily create a type to enforce non-nullable values of any reference type. Here's a pretty simple version of one as a script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#light

type NonNull<'a when 'a : null> =
    { Value : 'a }

let nnull x = 
    if x = null
        then failwith "null is not a valid value"
        else { Value = x }

type Content = 
    | Html of NonNull<string>

let c1 = Html(nnull "a string")
printfn "%A" c1 // Html {Value = "a string";}

try
    let c2 = Html(nnull null)
    ()
with ex -> printfn "Error: %s" ex.Message // Error: null is not a valid value

The big shortcoming here, of course, is that the non-null constraint is only enforced through the constructor function.

By on 1/13/2009 5:24 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper