- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个斐波那契序列生成器,我试图理解 Haskell 中的以下代码fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
我明白了zipWith
是,但我不完全知道程序是如何执行的,以及为什么它会生成所有的斐波那契数。我试图理解为什么它不会在函数式语言中使用环境概念终止,如下所示:
最初,由于 Haskell 的惰性求值,env
中的绑定(bind)应该是 fibs : [1,1,x]
,然后评估 fibs
,解释器评估 x
这是zipWith (+) fibs (tail fibs)
在这种情况下。在评估 zipWith
时, 它得到 fibs : [1,1,2,x]
,又是因为 Haskell 的懒惰评估。和fibs
在 env
绑定(bind)到 [1,1,2,x]
此时。但是,要全面评估 fibs
,它继续评估 x
我们回到前面的步骤。
它是否正确?
此外,我注意到当我在 ghci
中运行上面的程序时,它会立即提示它当前计算的斐波那契数列,为什么?一旦完成所有计算,它不应该打印结果吗?
最佳答案
所以,你的大部分推理都是正确的。特别是,您正确描述了如何根据旧元素评估列表中的每个新元素。您完全评估 fibs
也是正确的。将需要重复您概述的步骤,并且实际上会永远循环。
您缺少的关键要素是 我们不必全面评估列表 .像 fibs = ...
这样的绑定(bind)只需为表达式分配一个名称;它不需要评估整个列表。 Haskell 将只评估它需要运行 main
的列表。 .因此,例如,如果我们的 main
是
main = print $ fibs !! 100
fibs
的前 100 个元素(按照您概述的步骤)但不需要更多,也不会永远循环。
fibs
的值时,这正是正在发生的事情。在 ghci 中:它会尽可能多地打印每个正在计算的元素,而不必等到整个列表准备好。
ghci
中查看列表的评估量。使用
:sprint
命令将打印带有
_
的 Haskell 数据结构对于尚未评估的部分(称为“thunk”)。您可以使用它来查看
fibs
在行动中得到评估:
Prelude> let fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
Prelude> :sprint fibs
fibs = _
Prelude> print $ fibs !! 10
89
Prelude> :sprint fibs
fibs = _
fibs
获得多态类型
Prelude> :t fibs
fibs :: Num a => [a]
Num
类型类实例化为将字典传递给
fibs
;它的实现类似于
NumDictionary a -> [a]
函数。)
fibs
显式地单态。我们可以通过从限制处于事件状态的模块中加载它或给它一个明确的类型签名来做到这一点。让我们做后者:
Prelude> let fibs :: [Integer]; fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
Prelude> :sprint fibs
fibs = _
Prelude> print $ fibs !! 10
89
Prelude> :sprint fibs
fibs = 1 : 1 : 2 : 3 : 5 : 8 : 13 : 21 : 34 : 55 : 89 : _
fibs
示例(带有图表!)并讨论如何使用这种方法进行一般内存和动态编程。
关于haskell - 斐波那契数列生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28685119/
我是一名优秀的程序员,十分优秀!