我在玩弄语言开始学习,我对递归定义是如何工作的感到困惑。
例如,让我们以三角形数(TN n = sum [1..n]
)的序列为例
所提供的解决办法是:
triangularNumbers = scanl1 (+) [1..]
到现在为止还好。
但我想出的解决办法是:
triangularNumbers = zipWith (+) [1..] $ 0 : triangularNumbers
这也是正确的。
现在我的问题是:如何将其转化为较低级别的实现?当满足这样一个递归定义时,场景后面到底会发生什么呢?
发布于 2015-07-27 07:14:49
下面是一个简单的递归函数,它给出了第n个三角数:
triag 0 = 0
triag n = n + triag (n-1)
您的解决方案triag' = zipWith (+) [1..] $ 0 : triag'
更奇特:它是共同递归的(点击,点击)。不是通过将n个数降为较小输入的值来计算它,而是通过递归地指定下一个值来定义整个无限三角形数序列,给出一个初始段。
Haskell是如何处理这种共递归的?当它遇到您的定义时,不实际执行任何计算,它将被推迟到需要进一步计算的结果。当您访问list triag'
的特定元素时,Haskell开始根据定义计算列表中的元素,直到被访问的元素。关于更多细节,我发现关于懒惰评估的这文章很有帮助。总之,除非您需要预测内存的使用情况,否则懒散评估是很好的。
这里是一个类似的这样的问题,并逐步解释了fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
的求值,这是斐波那契序列的一种共递归定义。
https://stackoverflow.com/questions/31656294
复制相似问题