无法删除参数(无点样式Haskell)

时间:2016-02-08 21:22:12

标签: haskell functional-programming

我在删除此函数中的参数'e'时遇到问题:

numocc e = map length . (map . filter . (==)) e

该函数检查二维列表中的元素的出现次数(列表中的列表)。所以你称之为:

  

numocc 1 [[1,2],[2,3,2,1,1],[3]]

     

结果:[1,2,0]

参数 e 位于等号两侧的最右侧,并未包含在任何参数中。因此,我应该能够删除它以获得无点功能:

numocc = map length . (map . filter . (==))

但是我收到了这个错误:

  

在应用程序中输入错误   表达式:地图长度。地图。过滤器。 (==)   术语:地图长度   类型:[[b]] - > [INT]   不符合:([[a]] - > [[a]]) - > [INT]

这是什么问题?感谢。

1 个答案:

答案 0 :(得分:6)

您的原始功能正在被解析为

numocc e = (map length) . ((map . filter . (==)) e)

因此,您不能只删除e,因为它在技术上并未出现在定义的末尾。但是,如果您定义运算符

(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.:) = (.) . (.)

然后你可以把它写成

numocc = map length .: (map . filter . (==))

map . filter . (==)上的括号是必需的,因为由于固定规则,您无法混合..:

然而,在这一点上,你只是让这个功能更难阅读和维护。最好将其分解为更小的部分并引入一些中间名称,同时添加正确的类型签名并为函数提供更好的名称:

numOccurrences :: Eq a => a -> [a] -> Int
numOccurrences valueToCount values = length (filter (== valueToCount) values)

numOccurrencesInSublists :: Eq a => a -> [[a]] -> [Int]
numOccurrencesInSublists valueToCount = map (numOccurrences valueToCount)

这更具可读性,不依赖于花哨的操作员,更清楚地表达您的意图。由于在单个列表中计数的情况是一个单独的函数,您现在也可以在其他地方使用它。

请记住,优雅的代码并不是要让它尽可能地短,而是要尽可能地让它变得清晰。描述性名称(不一定是长名称),显式参数和小型可组合单位是最好的。