且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

F#中的空合并运算符?

更新时间:2022-06-14 23:15:26

是的,使用此 SO 答案中的一些小骇客"F#中的重载运算符".

Yes, using some minor hackery found in this SO answer "Overload operator in F#".

在编译时,可以内嵌对于单个运算符使用('a Nullable, 'a) ->'a('a when 'a:null, 'a) -> 'a的正确重载.甚至可以抛出('a option, 'a) -> 'a以获得更大的灵活性.

At compiled time the correct overload for an usage of either ('a Nullable, 'a) ->'a or ('a when 'a:null, 'a) -> 'a for a single operator can be inlined. Even ('a option, 'a) -> 'a can be thrown in for more flexibility.

为了提供更接近于c#运算符的行为,我设置了默认参数'a Lazy,以便除非原始值为null,否则不会调用其源.

To provide closer behavior to c# operator, I've made default parameter 'a Lazy so that it's source isn't called unless the original value is null.

示例:

let value = Something.PossiblyNullReturned()
            |?? lazy new SameType()

实施方式:

NullCoalesce.fs [要点]:

NullCoalesce.fs [Gist]:

//https://gist.github.com/jbtule/8477768#file-nullcoalesce-fs
type NullCoalesce =  

    static member Coalesce(a: 'a option, b: 'a Lazy) = 
        match a with 
        | Some a -> a 
        | _ -> b.Value

    static member Coalesce(a: 'a Nullable, b: 'a Lazy) = 
        if a.HasValue then a.Value
        else b.Value

    static member Coalesce(a: 'a when 'a:null, b: 'a Lazy) = 
        match a with 
        | null -> b.Value 
        | _ -> a

let inline nullCoalesceHelper< ^t, ^a, ^b, ^c when (^t or ^a) : (static member Coalesce : ^a * ^b -> ^c)> a b = 
        // calling the statically inferred member
        ((^t or ^a) : (static member Coalesce : ^a * ^b -> ^c) (a, b))

let inline (|??) a b = nullCoalesceHelper<NullCoalesce, _, _, _> a b

或者,我制作了一个库,该库利用此技术以及用于处理Null/Option/Nullables的计算表达式,称为

Alternatively I made a library that utilizes this technique as well as computation expression for dealing with Null/Option/Nullables, called FSharp.Interop.NullOptAble

它改用运算符|?->.