与功能组成混淆

Let*_*t4U 2 haskell function function-composition

开始学习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
Run Code Online (Sandbox Code Playgroud)

根据这个答案:Haskell:区别.(点)和$(美元符号) ".运算符的主要目的不是避免括号,而是链函数.它允许你将右边出现的任何内容的输出与左边显示的内容的输入联系起来. ".

好的,为什么我的例子不起作用?实际和预期的类型不同,但为什么?毕竟,根据这个描述map应该采取(double) ([1,2,3])输入并将其输出传递给sum输入?

AJF*_*mar 7

这样做的原因是.只允许函数在传递给下一个参数之前接受一个参数.所以:

(sum . map) double [1,2,3]
Run Code Online (Sandbox Code Playgroud)

会变成

(sum (map double)) [1,2,3]
Run Code Online (Sandbox Code Playgroud)

......我们不能总结一个功能,可以吗?输入错误很多!

你要做的是:

(sum . map double) [1,2,3]
Run Code Online (Sandbox Code Playgroud)

减少到:

sum (map double [1,2,3])
Run Code Online (Sandbox Code Playgroud)

如果你想看,这里有如何.定义:

(.) :: (b -> c) -> (a -> b) -> (a -> c)
(.) f g arg = f (g arg)
Run Code Online (Sandbox Code Playgroud)

如果你真的很聪明,你可以加倍地写一些东西,这样它在传递之前需要两个参数:

((sum .) . map) double [1,2,3]
Run Code Online (Sandbox Code Playgroud)

减少到:

(sum . map double) [1,2,3]
Run Code Online (Sandbox Code Playgroud)

最后:

sum (map double [1,2,3])
Run Code Online (Sandbox Code Playgroud)