输入与printfn不匹配

时间:2017-11-11 12:49:04

标签: f#

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

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


printfn "%s" concat "hello" "world"
  

类型不匹配。期待一个'字符串 - > ' a - > ' b - > ' C'但给出一个'字符串 - >单元'类型'' a - > ' b - > ' C'不匹配类型'单位' (使用外部F#编译器)

     

这个表达式应该有类型'字符串'但在这里   有类型'字符串 - > string - >字符串'

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

编辑:似乎我需要围绕调用concat的括号。为什么需要这个?

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


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

2 个答案:

答案 0 :(得分:5)

Robert Nielsen的回答是正确的,但让我尝试一种不同的方式来解释它,因为如果你是F#的新手,可能很难理解像这样的表达式:

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

所以想一想:在F#中,函数可以作为输入传递给其他函数。例如,您可以将concat函数作为输入传递给List.reduce

List.reduce concat ["one"; "two"; "three"]
// Returns "one, two, three"

现在,您可以通过两种方式阅读此内容。函数调用可以保留优先级或右优先级。即,如果函数调用具有正确的优先级,那么["one"; "two"; "three"]列表将被视为concat函数的第一个参数(因为它最右边因此具有优先权)。或者如果函数调用优先,那么该列表将是List.reduce函数的第二个参数,concat函数将是第一个参数。 F#使后者(左优先)成为默认值:在没有括号的情况下,函数名称后面的所有内容都被认为是该函数的参数。以下是:

printfn "%s" concat "hello" "world"

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

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

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

但请想一想:如果默认是相反的,并且函数调用具有正确的优先级 - 您如何将括号放入List.reduce示例中以使其按您想要的方式工作?你想要的是“用两个参数调用List.reduce:第一个是函数,第二个是字符串列表。”但是你如何为此添加括号:

List.reduce concat ["one"; "two"; "three"]

得到那个结果?嗯,这样可行:

(List.reduce concat) ["one"; "two"; "three"]

但在我看来,这会令人困惑。要理解这个表达式,你必须要了解F#currying是如何工作的,这是一个通常需要一段时间才能解决问题的概念。对于左优先级函数调用,表达式someFunction a b c总是表示“使用三个参数调用someFunction”,无论这三个参数中的任何一个都是函数。

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

答案 1 :(得分:2)

由于F-sharp运算符优先级:Symbol and Operator Reference

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

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

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

但是撒上了一些类型推断。