Haskell 递归还是列表理解?
学习Haskell非常好,在关于高阶函数的一章中,作者介绍了几个不同库函数的实现。当谈到Haskell 递归还是列表理解?,haskell,recursion,list-comprehension,Haskell,Recursion,List Comprehension,学习Haskell非常好,在关于高阶函数的一章中,作者介绍了几个不同库函数的实现。当谈到filter'(标准库函数filter的重新实现)的定义时,我认为显而易见的是: filter' f xs = [x | x <- xs, f x] 这两个定义的作用相同。这有什么原因吗?递归定义是否更有效?对Haskell来说,这更习惯吗?还有其他原因吗?可能是因为列表理解只是语法上的糖分,原则上可以转换为递归形式 如果作者的目的是说明函数是如何实现的,那么使用列表理解快捷方式并不能真正做到这一点—
filter'
(标准库函数filter
的重新实现)的定义时,我认为显而易见的是:
filter' f xs = [x | x <- xs, f x]
这两个定义的作用相同。这有什么原因吗?递归定义是否更有效?对Haskell来说,这更习惯吗?还有其他原因吗?可能是因为列表理解只是语法上的糖分,原则上可以转换为递归形式 如果作者的目的是说明函数是如何实现的,那么使用列表理解快捷方式并不能真正做到这一点——它显示了一种表达解决方案的替代方法,但实际上并不是一种函数实现 简而言之,它展示了如何从一组相当小的基本构建块实现
不过,这只是一个猜测——我自己还没有读过那个教程。列表理解对于一个地图和一个过滤器来说,在一次操作中是非常有用的;尽管它可能在后端使用concatMap。通常使用较高抽象的东西来实现较低抽象的东西是欺骗。
filter'
也可以用高阶函数foldr
编写,如filter'p=foldr(\x ys->如果px,那么x:ys,否则ys)[
,虽然这是一个使用高阶函数的更好例子,而不是如何“从头开始”构建一个高阶函数。看看你是否对它们的分解方式感兴趣。你不能仅仅用映射和过滤器来实现列表理解,你真的需要concatMap。@augustss为什么你认为我特别提到它使用concatMap?我的意思是,过滤器基本上是concatMap的一部分。“可能使用”听起来不像“必须使用”。)@augustss当然不必使用,你可以重新实现整个过程。我认为augustss在这里的观点是,concatMap
完全包含map
和filter
,以及做他们做不到的事情,任何创建列表理解的重新实现都必然等同于concatMap
。
filter' _ [] = []
filter' p (x:xs)
| p x = x : filter' p xs
| otherwise = filter' p xs