【发布时间】:2011-12-23 22:02:16
【问题描述】:
我想定义一个函数来计算列表中满足给定谓词的元素数量:
number_of_elements :: (a -> Bool) -> [a] -> Int
number_of_elements f xs = length (filter f xs)
例如:
number_of_elements (==2) [2,1,54,1,2]
应该返回2。
我们可以写得更短:
number_of_elements f = length . filter f
不带f参数可以写吗?
【问题讨论】:
-
您正在寻找的被称为“Pointfree 风格”。这里有一个关于它的维基:haskell.org/haskellwiki/Pointfree。它教你所有的技巧,比如猫头鹰:
((.)$(.))和点:((.).(.))。不过我个人不会推荐这种风格。 -
我建议您尝试一下,看看它是如何工作的,但使用部分无点样式
number_of_elements f = length . filter f。这通常是最易读的。 -
这是一个我很少会费心定义的函数,因为坦率地说,
length (filter f xs)比number_of_elements f xs更容易阅读。后者需要我通过查找函数定义、文档或从类型推断来弄清楚函数的作用;而前者是我已经理解的两个函数的直接组合使用——而且写起来也更短!我只会将其定义为where绑定中的辅助函数,或者作为未导出的模块函数——即使这样,也只有当它将成为其他函数的参数时。 -
sacundim 是完全正确的。如果您真的想要的不仅仅是
length (filter f xs),我建议在is7s 的答案中定义(.:)组合器,并根据需要使用length .: filter,但即使这样也有点傻。跨度>