是否有与此C#扩展方法等效的F#?

时间:2013-07-28 03:11:27

标签: c#-to-f#

我发现以下C#扩展方法非常有用:

public static bool In<T>(this T x, params T[] xs)
{
    return xs.Contains(x);
}

允许进行C#调用,例如

var s = "something else";
var rslt = s.In("this","that","other") ? "Yay" : "Boo";

var i = 1;
var rslt = i.In(1,2,3) ? "Yay" : "Boo";

我一直试图想出一个F#(近似)等价物,例如:

let s = "something else"
let rslt = if s.In("this","that","other") then "Yay" else "Boo"

似乎我需要类似的东西:

type 'T with

    static member this.In([ParamArray] xs : 'T  )
        {
            return xs.Contains(x);
        }

但这不是合法的F#语法。我无法看到如何在F#中的泛型类上声明扩展方法。可能吗?或者有更好的方法来实现类似的结果吗? (我想我可以在C#项目中链接并从F#中调用它,但那会欺骗!: - )

我能想到的最好的是:

let inline In (x : 'a, [<ParamArray>] xs : 'a[]) = Array.Exists( xs, (fun y -> x = y) )  

我希望允许这样的电话(无论如何都不能接受):

if In(ch, '?', '/') then "Yay" else "Boo"

但实际上需要:

if In(ch, [| '?'; '/' |]) then "Yay" else "Boo"

暗示ParamArray属性被忽略(原因我还没有理解)。

1 个答案:

答案 0 :(得分:2)

Fwiw,最新版本的F#(3.1)包含了我之后的所有内容(耶!):

[<Extension>] 
type ExtraCSharpStyleExtensionMethodsInFSharp () = 

    [<Extension>] 
    static member inline In(x: 'T, xs: seq<'T>) = xs |> Seq.exists (fun o -> o = x)

    [<Extension>] 
    static member inline Contains(xs: seq<'T>, x: 'T) = xs |> Seq.exists (fun o -> o = x)

    [<Extension>] 
    static member inline NotIn(x: 'T, xs: seq<'T>) = xs |> Seq.forall (fun o -> o <> x)

提供用法

 if s.In(["this","that","other"]) then ....
 if (["this","that","other"]).Contains(s) then ...