首页 > 解决方案 > 声明函数类型时语法不一致

问题描述

如果我正在创建一个函数,让我们举一个最简单的例子:

add x y = x + y

如果我想在之前添加一个函数类型声明,为了清楚起见

add :: (Int, Int) -> Int
add x y = x + y

我收到一个编译错误:
“无法将预期类型 'Int' 与实际类型 '(Int, Int) -> (Int, Int)' 匹配”。
“'add' 的方程有两个参数,但它的类型'(Int,Int)-> Int'只有一个“

但如果我将其纠正为

add :: (Int, Int) -> Int
add (x, y) = x + y

来自其他语言,我实际上认为使用带括号的第二种形式更清楚,但在我看来,两种方式都应该有效

1 - 不以第一种方式工作的原因是什么?
2 - 我发现错误消息完全令人困惑,所以,也许,错误发生的另一个原因我不明白

标签: haskell

解决方案


第一种方式不工作的原因是什么?

在第一个表达式中,您的类型表示它需要一个 2 元组作为单个参数,并返回两项之和。但是在函数的“主体”中,您指定add x y = x + y因此构造一个函数,该函数接受一个参数,该参数x将返回一个函数,该函数将接受一个y映射到x + y.

在 Haskell 中,所有函数都采用一个参数。实际上,您的add函数采用一个参数x。它的缩写:

add x = \y -> x + y

因此,它返回一个函数,该函数将接受一个参数y,然后映射yx + y. 如果您因此构造一个函数f = add 2,那么f将获取参数y,并将其映射到2 + y

箭头是右结合运算符。这意味着Int -> Int -> Int是 的缩写Int -> (Int -> Int),因此它是将 a 映射Int到另一个函数的函数。

您可以看到像 Java 这样的语言的语法,它们f (x, y)基本上调用函数f时使用一个对象:一个 2 元组,其中xy作为它的两个元素。


推荐阅读