map
的签名是(a -> b) -> [a] -> [b]
,这意味着它需要2个参数并返回一个列表。
然而,以下函数将字符串转换为首字母大写的克隆是错误的:
modernise :: String -> String
modernise s = unwords . map (\m -> [toUpper (head m)] ++ tail m) (words s)
好的版本是:
modernise :: String -> String
modernise = unwords . map (\m -> [toUpper (head m)] ++ tail m) . words
第一个版本被拒绝,并显示错误消息: "too many arguments for the map function"
;但是我提供了两个参数(lambda函数和words
的结果),这是很多参数。
答案 0 :(得分:4)
您需要application operator (.) :: (b -> c) -> (a -> b) -> a -> c
而不是功能组合modernise s = unwords $ map (\m -> [toUpper (head m)] ++ tail m) (words s)
的点。
modernise s = unwords ( map (\m -> [toUpper (head m)] ++ tail m) (words s) )
与
相同{{1}}
答案 1 :(得分:4)
在第一个版本中,你写了
modernise s = unwords . map whatever (words s)
根据.
的定义,这意味着
modernise s = \x -> unwords (map whatever (words s) x)
您可以改为使用$
运算符:
modernise s = unwords $ map whatever (words s)
但是你开始工作的版本完全是惯用的和清晰的,所以没有必要改变它的结构方面。
答案 2 :(得分:2)
"地图功能的参数太多了&#34 ;;但是我给出了2个参数(lambda函数和"单词"的结果),这是很多参数。
完全。在子表达式map (\m -> [toUpper (head m)] ++ tail m) (words s)
中,您给了map
两个参数,并且得到了类型为[String]
的值,这是一个非函数类型。但是,您将结果视为函数,因为(.)
的第二个参数必须是函数类型。
每当您尝试提供需要函数的非函数值时,编译器都会提供诊断。有问题的子表达式是函数map
的多重应用,这就是为什么编译器会建议你可能试图用太多的参数来提供它。
正如其他人已经说过的那样,你需要($)
函数。