开始学习Haskell:
*Main> map double [1,2,3]
[2,4,6]
*Main> sum (map double [1,2,3])
12
*Main> (sum . map) (double) ([1,2,3])
<interactive>:71:8:
Couldn't match type ‘[b0] -> [b0]’ with ‘[[t0] -> t]’
Expected type: (b0 -> b0) -> [[t0] -> t]
Actual type: (b0 -> b0) -> [b0] -> [b0]
Relevant bindings include it :: t (bound at <interactive>:71:1)
Probable cause: ‘map’ is applied to too few arguments
In the second argument of ‘(.)’, namely ‘map’
In the expression: sum . map
根据这个答案:Haskell: difference between . (dot) and $ (dollar sign)“。运算符的主要目的不是避免括号,而是链函数。它允许你将右边显示的内容的输出与出现的任何内容的输入联系起来在左边。”。
好的,为什么我的例子不起作用?实际和预期的类型不同,但为什么?毕竟,根据此说明,map
应该对输入采用(double) ([1,2,3])
并将其输出传递给sum
的输入?
答案 0 :(得分:7)
原因是.
只允许函数在传递给下一个参数之前使用一个参数。所以:
(sum . map) double [1,2,3]
将成为
(sum (map double)) [1,2,3]
...我们无法总结一个功能,可以吗?输入错误!
你要做的是:
(sum . map double) [1,2,3]
减少到:
sum (map double [1,2,3])
如果你想看,这里是.
的定义方式:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(.) f g arg = f (g arg)
如果你真的很聪明,你可以加倍地写一些东西,这样它在传递之前需要两个参数:
((sum .) . map) double [1,2,3]
减少到:
(sum . map double) [1,2,3]
最后:
sum (map double [1,2,3])