[英]Why doesn't Haskell accept arguments after a function composition?
考虑到 Haskell 有柯里化功能,我们可以这样做:
foo a b = a + b -- equivalent to `foo a = \b -> a + b`
foo 1 -- ok, returns `\b -> 1 + b`
foo 1 2 -- ok, returns 3
声明返回 lambda 的函数,就像在注释中一样,也可以正常工作。
但是当我组合这些函数时,就像这样:
foo a b = a + b
bar x = x * x
bar . foo 1 -- ok, returns a lambda
bar . foo 1 2 -- wrong, I need to write `(bar . foo 1) 2`
然后它会导致错误。
问题是:为什么函数组合周围的括号是必要的?
假设您已经在 GHCi 中定义了以下内容:
λ> let foo a b = a + b
λ> let bar x = x * x
bar . foo 1 2
相当于
(bar . foo 1) 2
但是,请记住,函数应用程序(空格)的优先级高于组合运算符( .
); 所以
bar . foo 1 2
真的相当于
bar . ((foo 1) 2)
现在,让我们看看这些类型:
.
有类型(b -> c) -> (a -> b) -> a -> c
; 它的两个参数是函数(可以组合)。bar
类型为Num a => a -> a
,因此与 的第一个参数的类型 ( b -> c
) 兼容.
.foo 1 2
类型为Num a => a
; 它是一个(多晶型)的数字常数,而非函数,并且因此不与类型兼容( a -> b
的第二个参数的) .
. 这就是您在bar . foo 1 2
收到类型错误的原因bar . foo 1 2
bar . foo 1 2
。 不过,你可以做的是
bar $ foo 1 2
因为$
运算符的类型为(a -> b) -> a -> b
。 请参阅Haskell: . (点)和 $(美元符号)
bar . foo 1 2
bar . foo 1 2
是bar . (foo 1 2)
bar . (foo 1 2)
不是(bar . foo 1) 2
这里没有任何与 lambda 相关的神秘事情。 假设我们将foo
的应用扩展为 1:
bar . foo 1 2
bar . (\b -> 1 + b) 2
现在,我们将 lambda 应用于 2
bar . 3
这就是你的问题。
相反,如果我们正确放置括号,我们会像这样评估它:
(bar . foo 1) 2
(bar . (\b -> 1 + b)) 2
(\x -> bar ((\b -> 1 + b) x)) 2
bar 3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.