F#中的空融合运算符?

时间:2014-01-17 19:46:56

标签: f# null null-coalescing-operator null-coalescing

当与C#库交互时,我发现自己想要Nullable结构和引用类型的C#的空合并运算符。

是否可以在F#中使用一个内联相应if案例的重载运算符对其进行近似?

3 个答案:

答案 0 :(得分:25)

是的,使用此 SO 回答“Overload operator in F#”中找到的一些小错误。

在编译时,可以为单个运算符使用('a Nullable, 'a) ->'a('a when 'a:null, 'a) -> 'a的正确重载。即使('a option, 'a) -> 'a也可以投入使用以获得更大的灵活性。

为了提供更接近c#运算符的行为,我已经设置了默认参数'a Lazy,因此除非原始值为null,否则不会调用它的源。

示例:

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

<强>实施

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的计算表达式,称为FSharp.Interop.NullOptAble

它使用运算符|?->代替。

答案 1 :(得分:4)

the accepted answer修改了jbtule以支持DBNull:

let inline (|??) a b = nullCoalesceHelper<NullCoalesce, _, _, _> a b
let o = box null
let x = o |?? lazy (box 2)
let y = (DBNull.Value) |?? lazy (box 3)
let z = box (DBNull.Value) |?? lazy (box 4)
let a = None |?? lazy (box 5)
let b = box None |?? lazy (box 6)
let c = (Nullable<int>() ) |?? lazy (7)
let d = box (Nullable<int>() ) |?? lazy (box 8)

用法:

def lucky_sevens?(numbers)
  numbers.each_cons(3).any?{|x, y, z| x + y + z == 7}
end

答案 2 :(得分:0)

我通常为此目的使用defaultArg,因为它是语言的内置语言。