haskell:良好的地图用法,参数数量

时间:2015-10-06 16:01:45

标签: haskell

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的结果),这是很多参数。

你可以帮帮我吗?

3 个答案:

答案 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的多重应用,这就是为什么编译器会建议你可能试图用太多的参数来提供它。

正如其他人已经说过的那样,你需要($)函数。