2

我发现以下 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 属性被忽略(出于我尚未理解的原因)。

4

1 回答 1

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 ...

等等

于 2013-11-18T01:54:36.287 回答