【问题标题】:Recursion or list comprehension?递归还是列表理解?
【发布时间】:2011-10-01 23:00:48
【问题描述】:

Working through Learn You a Haskell For Great Good,在关于高阶函数的章节中,作者介绍了几个不同库函数的实现。当谈到filter'(标准库函数filter的重新实现)的定义时,我认为显而易见的是:

filter' f xs = [x | x <- xs, f x]

但作者给出了以下更长的递归定义:

filter' _ [] = []  
filter' p (x:xs)   
    | p x       = x : filter' p xs  
    | otherwise = filter' p xs

两个定义做同样的事情。这有什么原因吗?递归定义是否更高效?对 Haskell 来说更惯用吗?还有什么?

【问题讨论】:

  • filter' 也可以用高阶函数 foldr 来写,就像在 filter' p = foldr (\x ys -&gt; if p x then x : ys else ys) [] 中一样,尽管这将是使用高阶函数的一个更好的例子,而不是如何“从头开始”构建一个。
  • 如果您对它们如何脱糖感兴趣,请参阅Haskell 2010 > Expressions > List Comprehensions

标签: haskell recursion list-comprehension


【解决方案1】:

这可能是因为列表理解只是语法糖,原则上被翻译成递归形式。

如果作者的观点是为了说明函数是如何实现的,那么使用列表理解快捷方式并不能真正做到这一点 - 它显示了表达解决方案的另一种方式,但并不是真正的函数式实现。

简而言之,它展示了如何从一组相当少的基本构建块中实现。

不过,这只是猜测 - 我自己还没有阅读过该教程。

【讨论】:

    【解决方案2】:

    列表理解几乎是一个操作中的映射和过滤器的糖;虽然它可能在后端使用 concatMap 。通常使用较高抽象的东西来实现较低抽象的东西是作弊。

    【讨论】:

    • 你不能仅仅用 map 和 filter 来实现列表推导,你真的需要 concatMap。
    • @augustss 为什么你认为我特别提到它使用 concatMap?我得到的是过滤器基本上是 concatMap 的一部分。
    • “可以使用”听起来不像“必须使用”。 :)
    • @augustss 当然不一定要用,你可以重新实现整个东西。
    • 我认为 augustss 的观点是 concatMap 完全包含 mapfilter,以及做他们不能做的事情,并且任何用于创建列表推导的重新实现都必然是相当于concatMap
    猜你喜欢
    • 2015-03-10
    • 2020-10-17
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-09
    相关资源
    最近更新 更多