如何在F#中编写一个带有可变数量参数的函数

Ant*_*eru 28 c# f#

我在C#中有一个函数,我想将它(在其他一些东西中)移植到F#,只是为了做到这一点.不幸的是,我只是遇到了一个似乎没有办法在F#中表达这种情况的案例:拿这个C#函数

public static T Min<T>(params T[] p) where T : IComparable
{
    T m1 = p[0];

    foreach (T v in p)
    {
        m1 = (m1.CompareTo(v) < 0) ? m1 : v;
    }

    return m1;
}
Run Code Online (Sandbox Code Playgroud)

我认为这很容易,但我不明白如何在F#中指定变量参数列表.我试过这个:

let rec Min l =
    match l with
    | [] -> 0 // should throw exception here
    | [v] -> v
    | (h::t) -> min h (Min t)
Run Code Online (Sandbox Code Playgroud)

但是从C#调用它需要一个Microsoft.FSharp.Collections.List.有可能让它期待一个params T[],如果是这样,怎么样?

Mic*_*lGG 28

如Jon所说,params数组只是一个带属性的数组.在参数之前添加属性.

let test ([<ParamArray>] arr : 'a array) = 
    if arr.Length = 0 then invalid_arg "arr"
    // ....
Run Code Online (Sandbox Code Playgroud)

您无需指定类型:

let test ([<ParamArray>] arr) = ... // lets type inference do its thing
Run Code Online (Sandbox Code Playgroud)

但是......模式匹配对数组类型不起作用.您可以编写一个活动模式来提供帮助.基本上,您必须决定什么更重要:F#代码或C#代码.当您设计高阶函数,使用元组,使用有区别的联合等时,同样的权衡将适用.C#不能表达大多数事物,而F#目前不支持C#中的一些小部分(表达式树写入例如,编译器).

  • 但是,在F#中,参数数组只能在方法中定义.它们不能用于模块中定义的独立功能或功能.http://msdn.microsoft.com/en-us/library/vstudio/dd233213.aspx所以让test([<ParamArray>] arr)不能正常工作 (2认同)
  • 根据我的测试, let `f ([&lt;System.ParamArray&gt;] args) = args` 将编译得很好。但是,它不需要可变数量的参数。如果您尝试传递不是数组的内容,它会引发编译器错误。另一方面,“type X() = static member F([&lt;System.ParamArray&gt;] args) = args”可以采用可变数量的参数,但不是正确的 F# 函数,无法组合或柯里化 (2认同)

Jon*_*eet 6

你想从F#或C#调用这个方法吗?这个hubFS帖子似乎表明F#不支持调用端的参数数组,但是我怀疑如果你为参数使用普通类型注释使它成为一个数组,并且还用ParamArrayAttribute来装饰它,你应该能够用C#中的变量参数调用它.

不能说我已经看过如何使用F#中的属性来装饰一个参数,但是如果你想要的话我可以寻找... 这个博客文章提供了几个例子,但不是在参数级别.