F# 类型与printfn不匹配

F# 类型与printfn不匹配,f#,F#,我有一个函数,它连接两个字符串,并在它们之间放置逗号和空格,然后返回。但是我不能打印结果 let concat first second = first + ", " + second printfn "%s" concat "hello" "world" 类型不匹配。应为'string->'a->'b->'c',但给定'string->unit',类型'a->'b->'c'与类型'unit'不匹配(使用外部F编译器) 此表达式应具有“string”类型,但此处 具有“字符串->字

我有一个函数,它连接两个字符串,并在它们之间放置逗号和空格,然后返回。但是我不能打印结果

let concat first second =
    first + ", " + second


printfn "%s" concat "hello" "world"
类型不匹配。应为'string->'a->'b->'c',但给定'string->unit',类型'a->'b->'c'与类型'unit'不匹配(使用外部F编译器)

此表达式应具有“string”类型,但此处 具有“字符串->字符串->字符串”类型

如何正确打印返回的字符串

编辑:看来我需要用括号括住对concat的调用。为什么需要这样做

let concat first second =
    first + ", " + second


printfn "%s" (concat "hello" "world")

由于F-sharp运算符的优先级:

编辑:您可以将其视为旋转

(((printfn "%s") concat) "hello") "world"
进入


罗伯特·尼尔森的答案是正确的,但让我试着用另一种方式来解释,因为如果你是F#的新手,可能很难理解这样的表达:

(((printfn "%s") concat) "hello") "world"
所以可以这样想:在F#中,函数可以作为输入传递给其他函数。例如,您可以将
concat
函数作为输入传递给
列表。reduce

List.reduce concat ["one"; "two"; "three"]
// Returns "one, two, three"
现在,有两种方法可以让你阅读。函数调用可以具有左优先级,也可以具有右优先级。也就是说,如果函数调用具有正确的优先级,那么
[“一”;“二”;“三”]
列表将被视为
concat
函数的第一个参数(因为它是最右边的,因此具有优先级)。或者,如果函数调用具有左优先级,则该列表将是
list.reduce
函数的第二个参数,而
concat
函数将是第一个参数。F#使后一个(左优先)成为默认值:在没有括号的情况下,函数名后面的所有内容都被视为该函数的参数。因此,以下是:

printfn "%s" concat "hello" "world"
读作:“使用四个参数调用
printfn
函数:一个字符串、一个函数和另外两个字符串”。如果希望字符串“hello”和“world”作为
concat
的参数,则必须添加括号,以便F#以更高的优先级解析
concat
调用(正如您已经发现的):

这被理解为:“使用两个字符串作为参数调用
concat
函数,然后将该函数调用的结果作为第二个参数传递给
printfn

但是请想一想:如果默认值是另一种情况,并且函数调用具有正确的优先级,那么如何将括号放入
列表中。减少
示例以使其按您想要的方式工作?您需要的是“调用
List.reduce
,其中包含两个参数:第一个是函数,第二个是字符串列表。”但如何在其中添加括号:

List.reduce concat ["one"; "two"; "three"]
为了得到那个结果?好吧,这会有用的:

(List.reduce concat) ["one"; "two"; "three"]
但在我看来,这会令人困惑。要理解这个表达方式,你必须理解F#currying是如何工作的,这是一个通常需要花一点时间才能理解的概念。而对于左优先函数调用,表达式
someFunction a b c
始终表示“调用
someFunction
,使用三个参数”,无论这三个参数中是否有一个是函数


我希望这个冗长的解释能帮助您更好地理解F#函数调用。

错误告诉您:printfn在抱怨-它得到了
%s”
现在需要一个
字符串
但是得到了一个包含多个参数的函数:
这个表达式应该有'string'类型,但是这里有'string->string->string'
你的最后一个例子可能应该是
(List.reduce concat)[“one”;“two”;“three”]
尽可能清晰。我想到了,但是决定,对于一个可能还没有摸索过咖喱概念的F#新手来说,这可能会让他们感到困惑,而不是帮助他们。编辑:改变了我的想法。你说得对,我应该展示一下它是如何工作的。
List.reduce concat ["one"; "two"; "three"]
(List.reduce concat) ["one"; "two"; "three"]