[英]Manipulating Lists in Haskell using Higher-Order Functions and Lambda Calculus
[英]Haskell using Higher-Order Functions to count how many items there are in a list
我正在尝试编写一行Haskell,以对列表中两个规定的上限和下限之间的项目数进行计数,例如countBetween 3 6 [5, 9, 2, 4, 6, 3, 1, 4] = 5
因为5、4、6、3和4在边界3和6之间。
到目前为止,我有:
countBetween x1 x2 = filter (>=x1) . filter (<=x2)
哪个过滤器列表仅包含那些范围内的数字,但我不知道如何计算列表拥有的项目数。 我最初的想法是,它将使用文件foldr
?
为了直接回答这个问题,有一个称为hoogle的Haskell工具。 我们希望length
函数的类型为[a] -> Int
,如果我们在搜索中逐字搜索,最终得到
length :: [a] -> Int
所以
countBetween x y = length . filter (>= x) . filter (<= y)
注意点,因为我们正在继续编写函数。
要将我的评论变成答案:
您需要使用length
功能。 在这种情况下,您可以将其与已经拥有的
countBetween lower upper = length . filter (>= lower) . filter (<= upper)
另外,您可以将函数的完整参数定义为
countBetween lower upper xs = length $ filter (>= lower) $ filter (<= upper) xs
减少eta的一般经验法则是首先将您的所有$
变成.
s并在最后一个参数之前添加$
,因此上一行变为
countBetween lower upper xs = length . filter (>= lower) . filter (<= upper) $ xs
然后,您查看定义的最后一个参数是否也是表达式的最后一个参数,并且它是表达式中唯一出现该参数的位置
countBetween lower upper xs = length . filter (>= lower) . filter (<= upper) $ xs
-- ^ ^
现在可以将其删除,让您
countBetween lower upper = length . filter (>= lower) . filter (<= upper)
然后重复。 在这种情况下,您无法再(轻松)进行eta减少,那么就完成了!
我还建议先使用完整的参数定义函数,然后再慢慢引入无点版本。 有时,找到巧妙的方法来对表达式进行eta简化会很有趣,但是尽管可以通过一些定义将其进一步推广,但并不总是建议这样做。 仅在自然且易于阅读的地方使用。 例如,使用pointfree
包中的pointfree
工具,您可以将定义完全减少到
countBetween = ((length .) .) . (. (filter . flip (<=))) . (.) . filter . flip (>=)
但这很难理解。 不要这样
虽然最好使用内置的长度功能,但以下是将“可怜的人的长度”与文件夹一起使用的解决方案:
countBetween x1 x2 = foldr (\v len -> len + 1) (0) . filter (>= x1) . filter (<= x2)
长度由文件夹计算:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.