F#如何编译可以将多个不同的参数类型转换为IL的函数? [英] How does F# compile functions that can take multiple different parameter types into IL?

查看:127
本文介绍了F#如何编译可以将多个不同的参数类型转换为IL的函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我几乎不了解F#。我甚至不知道语法,所以我不能给出例子。



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

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

,在CIL中,您不能声明此表单的委托。每个代理必须具有单个特定的参数类型列表。因为F#中的函数是一流的公民,然而,它似乎应该能够传递这样的函数,唯一的方法编译成CIL是使用委托。



那么,F#如何编译为CIL?

解决方案

函数可以接受多个不同的参数集,只需创建方法重载:

  string f(int x)
{
returnint+ x;
}
string f(string x)
{
returnstring+ x;
}
void callF()
{
Console.WriteLine(f(12));
Console.WriteLine(f(12));
}
//没有办法写这样的函数:
void call(Func< int | string,string> func)
{
Console.WriteLine (func(12));
Console.WriteLine(func(12));
}

callF 函数是非常简单,但是我的调用函数的语法不起作用。



写F#,你需要一个可以接受多个不同参数集的函数,你创建一个歧视的联合,可以包含所有不同的参数集,你做一个单一的函数,需要该联合:

  type Either = Int int 
|的Int字符串
let f = function Int x - > int+ string x
| String x - > string+ x

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

让调用func =
printfn%s(func(Int 12))
printfn%s(func(String12))

作为单个函数, f 可以像任何其他值,所以在F#中我们可以写 callF 调用f ,两者做同样的事情。

那么F#如何实现上面创建的 Either 类型呢?基本上这样:

  public abstract class 
{
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; }
}
}

调用函数是:

  public static void call(FSharpFunc< Either,string> f); 

并且 f 看起来像这样: / p>

  public static string f(_arg1)
{
if(_arg1是Either.Int)
returnint+((Either.Int)_arg1).Item;
returnstring+((Either.String)_arg1).Item;
}

当然你可以实现相同的 code>键入C#(duh!),但它不是惯用的,这就是为什么它不是上一个问题的明显答案。


I know virtually nothing about F#. I don’t even know the syntax, so I can’t give examples.

It was mentioned in a comment thread that F# can declare functions that can take parameters of multiple possible types, for example a string or an integer. This would be similar to method overloads in C#:

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

However, in CIL you cannot declare a delegate of this form. Each delegate must have a single, specific list of parameter types. Since functions in F# are first-class citizens, however, it would seem that you should be able to pass such a function around, and the only way to compile that into CIL is to use delegates.

So how does F# compile this into CIL?

解决方案

When you're writing C# and you need a function that can take multiple different parameter sets, you just create method overloads:

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"));
}

The callF function is trivial, but my made-up syntax for the call function doesn't work.

When you're writing F# and you need a function that can take multiple different parameter sets, you create a discriminated union that can contain all the different parameter sets and you make a single function that takes that union:

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"))

Being a single function, f can be used like any other value, so in F# we can write callF and call f, and both do the same thing.

So how does F# implement the Either type I created above? Essentially like this:

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; }
    }
}

The signature of the call function is:

public static void call(FSharpFunc<Either, string> f);

And f looks something like this:

public static string f(Either _arg1)
{
    if (_arg1 is Either.Int)
        return "int " + ((Either.Int)_arg1).Item;
    return "string " + ((Either.String)_arg1).Item;
}

Of course you could implement the same Either type in C# (duh!), but it's not idiomatic, which is why it wasn't the obvious answer to the previous question.

这篇关于F#如何编译可以将多个不同的参数类型转换为IL的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆