繁体   English   中英

Haskell使用高阶函数来计算列表中有多少项

[英]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)

长度由文件夹计算:

  • 我们从0的累加器开始
  • 对于每个列表元素v,我们只需将1加到累加器

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM