我对F#几乎一无所知。我什至不知道语法,所以我无法举例子。

在注释线程中提到,F#可以声明可以采用多种可能类型的参数(例如字符串或整数)的函数。这类似于C#中的方法重载:

public void Method(string str) { /* ... */ }
public void Method(int integer) { /* ... */ }

但是,在CIL中,您不能声明此形式的委托(delegate)。每个委托(delegate)必须有一个单独的,特定的参数类型列表。由于F#中的函数是一等公民,因此,您似乎应该可以传递此类函数,并且将其编译为CIL的唯一方法是使用委托(delegate)。

那么F#如何将其编译为CIL?

最佳答案

在编写C#时,需要一个可以采用多个不同参数集的函数,只需创建方法重载即可:

string f(int x)
{
    return "int " + x;
}
string f(string x)
{
    return "string " + x;
}
void callF()
{
    Console.WriteLine(f(12));
    Console.WriteLine(f("12"));
}
// there's no way to write a function like this:
void call(Func<int|string, string> func)
{
    Console.WriteLine(func(12));
    Console.WriteLine(func("12"));
}
callF函数微不足道,但是我为call函数编写的语法不起作用。

在编写F#时,需要一个可以采用多个不同参数集的函数,然后创建一个可以包含所有不同参数集的有区别的并集,并创建一个采用该并集的单个函数:
type Either = Int of int
            | String of string
let f = function Int x -> "int " + string x
               | String x -> "string " + x

let callF =
    printfn "%s" (f (Int 12))
    printfn "%s" (f (String "12"))

let call func =
    printfn "%s" (func (Int 12))
    printfn "%s" (func (String "12"))

作为一个函数,f可以像其他任何值一样使用,因此在F#中,我们可以编写callFcall f,并且两者都做相同的事情。

那么F#如何实现上面创建的Either类型?本质上是这样的:
public abstract class Either
{
    public class Int : Test.Either
    {
        internal readonly int item;
        internal Int(int item);
        public int Item { get; }
    }
    public class String : Test.Either
    {
        internal readonly string item;
        internal String(string item);
        public string Item { get; }
    }
}
call函数的签名为:
public static void call(FSharpFunc<Either, string> f);
f看起来像这样:
public static string f(Either _arg1)
{
    if (_arg1 is Either.Int)
        return "int " + ((Either.Int)_arg1).Item;
    return "string " + ((Either.String)_arg1).Item;
}

当然,您可以在C#中实现相同的Either类型(duh!),但这不是惯用的,这就是为什么它不是上一个问题的明显答案。

10-07 13:14
查看更多