简体   繁体   中英

Allowing nulls on a record type F#

I'm trying to make a type extension for MongoDB C# Driver that will return an option type instead of null when trying to execute a query that yields 0 results.

I've run into a few issues on the way, but right now there is just one thing in the way.

Here is the code

[<Extension>]
type Utils () =
    [<Extension>]
    static member inline tryFindOne(x: MongoCollection<'T>, query) =
        match x.FindOne(query) with
        | null -> None
        | value -> Some value

[<CLIMutable>]
type Entity = 
    { Id : ObjectId; Name : string }
    static member Create(name) =
        { Id = ObjectId(); Name = name }

The problem of course is that the record type Entity to the F# compiler does not conform to the type constraint of the extension method( 'T : null ) but I have to have the contraint to be able to pattern match against nulls. Of course it's sort of a nonsensical thing because the type Entity is very much "nullable" for interop purposes and will be returned as null whenever you try to query a MongoDB collection which yields 0 results. I tried to set the attribute [<AllowNullLiteral>] but unfortunately it only works with classes. So alas I'm stuck, I could make Entity into a class instead but I think records are more idiomatic F#.

I think the following should work:

[<Extension>]
type Utils () =
[<Extension>]
static member inline tryFindOne(x: MongoCollection<'T>, query) =
    let theOne = x.FindOne(query);
    if (box theOne = null) None else Some(theOne)

I have borrowed the idea from Sergey Tihon's post here: https://sergeytihon.wordpress.com/2013/04/10/f-null-trick/

Alternative way to do the null check without boxing:

[<Extension>]
type Utils () =
    [<Extension>]
    static member inline tryFindOne(x: MongoCollection<Entity>, query) =
        let theOne = x.FindOne(query)
        if obj.ReferenceEquals(theOne, null) then None else Some(theOne)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM