既然函数是F#中的一级值,为什么';我不能使用lambda作为值吗?

既然函数是F#中的一级值,为什么';我不能使用lambda作为值吗?,f#,F#,如果我定义一个简单的函数: let myConcat a b = a + "+" + b 然后假设函数是F#中的一级值,我希望能够像这样使用myConcat: let result = myConcat "a" (fun () -> "b") 它没有生成字符串“a+b”,而是给出以下错误: error FS0002: This function takes too many arguments, or is used in a context where a function

如果我定义一个简单的函数:

let myConcat a b = 
    a + "+" + b
然后假设函数是F#中的一级值,我希望能够像这样使用
myConcat

let result = myConcat "a" (fun () -> "b")
它没有生成字符串“a+b”,而是给出以下错误:

error FS0002: This function takes too many arguments, or is used in a context where a function is not expected
希望我只是把语法弄错了,但在我看来函数不能真正用作F#中的值。有人能解释一下这是怎么回事吗

编辑 为了进一步澄清我的问题,我可以使用等效的C代码:

但是,如果我想在param b中传递一个“call later function”,我必须:

public string myConcat(string a, Action<string> b) { return a + "+" + b(); }
public string myConcat(string a,Action b){返回a++“++”+b();}
或者我可以这样称呼它:

Func<string> b = () => "b";
var result = myConcat("a", b());
Func b=()=>“b”;
var结果=myConcat(“a”,b());

据我所知,C#没有声称函数是一级值。F#确实提出了这一主张。那么,当我不能将一个单位->字符串函数视为“惰性评估”字符串值时,有什么区别呢?

你可以这样称呼它:
let result=myConcat“a”((fun()->“b”)())

创建myConcat时,它被解释为:
val myConcat:a:string->b:string->string

它希望第二个参数是字符串,而您正在向它传递一个方法

要执行您想要的操作,您必须将myConcat声明为
让myConcat a b=a++“++”b()
然后您可以传入一个函数作为第二个参数


然后,这将被解释为
val myConcat:a:string->b:(unit->string)->string

您正在创建的lambda具有类型(unit->string)。然后你试图打一个电话,结果是

字符串->字符串->(单元->字符串)->字符串

预期调用应具有类型的时间

字符串->字符串->字符串->字符串

因此,您试图传入lambda,而实际上您想要传入的是调用lambda的结果

let result = myConcat "a" ((fun() -> "b")())

多亏了Mauricio Scheffer,我对我的问题有了答案:

C#和许多其他语言也提供“函数是一流的值”。然而,作为一种面向对象语言,在C语言中,这通常表示为“函数是一级对象”。短语“函数是一级值”只是指通过参数将函数引用传递给另一个函数的能力,就像它是一个值一样。对于eg unit->string值,并没有“神奇”的解释,它等同于正在进行的字符串值,只是unit->string函数是传递给另一个值的有效值

由于F#强大的类型推断功能,我不需要像使用C#那样在F#中指定引用函数的unit->string类型,但是编译器会推断出这种类型,因此如果不先将其包装在匿名unit->string函数中,我就无法只传递一个简单的字符串


如果您比我更了解这些内容,并且我有错误,请执行编辑以更正任何错误。

您的函数不只是希望任何值作为第二个参数,它需要一个字符串。函数不是字符串。如果返回字符串的函数不能被视为字符串值,那么当函数在F#?@DavidArno中被描述为值时,这意味着什么这意味着该语言支持将函数作为参数传递给其他函数,将其作为其他函数的值返回,并将其分配给变量或存储在数据结构中“@DavidArno函数自2.0以来一直是C#中的一流值。关于第一类函数的更多信息:@MauricioScheffer:我明白了。在这种情况下,我看不出在C#中使用构造函数、属性或方法作为函数所必须做的工作与在C#中结合函数指针和环境所必须做的工作之间有什么明显的区别。所以C也有一流的函数?:-)谢谢你的回答。虽然它没有直接回答这个问题,但它仍然有助于解释我在哪里感到困惑。投票结果是向上的。谢谢你的回答。虽然它没有直接回答这个问题,但它仍然有助于解释我在哪里感到困惑。结果是投票结果。
let result = myConcat "a" ((fun() -> "b")())