【问题标题】:Number of elements in Haskell in pointfree styleHaskell中无点样式的元素数量
【发布时间】: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,但即使这样也有点傻。跨度>

标签: haskell filter pointfree


【解决方案1】:

没错:

number_of_elements = (length .) . filter

【讨论】:

  • 谢谢,您能解释一下为什么(length . filter)(length $ filter) 不起作用吗?
  • @vikingsteve,好吧,length . fitler 扩展为 \x -> length (filter x)。这里filter x 是一个函数,无论这意味着什么,你都无法计算函数的长度。同样,length $ filter 正在尝试计算 filter 函数的长度。
【解决方案2】:

我不认为你可以比你建议的更具可读性。但是,为了好玩,您可以这样做:

numberOfElements = (.) (.) (.) length filter

(.:) = (.) . (.)
numberOfElements = length .: filter

【讨论】:

  • (.*) 通常称为(.:);例如,lambdabot 这么称呼它。
  • @C.A.McCann 可能是因为 (.) 短一个字符? :)
  • 我个人更喜欢.*,事实上我上传了一个哑包到hackage(“composition”包),它在Data.Composition下定义它
  • 语义编辑器组合样式的一个奇妙特性——fmap.fmapresult.result——是它始终如一地组合。如果您想深入三层,只需添加第三个fmapresult(或firstsecond 等)。相反,当您添加或删除fmaps 时,fmap fmap fmap 变得完全不同。
【解决方案3】:

您可能想了解Semantic Editor Combinators。从那里获取result 组合器:

result :: (output -> output') -> (input -> output) -> (input -> output')
result = (.)

result 组合器接受一个函数并将其应用于另一个函数的结果。现在,看看我们拥有的功能:

filter :: (a -> Bool) -> [a] -> [a]
length :: [a] -> Int

现在,length 适用于 [a] 的;它碰巧是foo :: [a] -> [a] 形式的函数的结果类型。所以,

result length :: ([a] -> [a]) -> ([a] -> Int)

但是filter的结果正好是一个[a] -> [a]函数,所以我们要把result length应用到filter的结果上:

number_of_elements = result (result length) filter

【讨论】:

  • 我将重写最后一行以隔离组合的 SEC(语义编辑器组合器):number_of_elements = (result.result) length filter。读作:通过将length 应用于filter 的结果来计算元素的数量。这里(result.result) 是编辑器组合器,length 是(语义)编辑器。一定要阅读SEC post
猜你喜欢
  • 2012-03-14
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 2018-03-06
  • 1970-01-01
  • 1970-01-01
  • 2019-12-21
  • 2020-08-22
相关资源
最近更新 更多