我是Haskell的新手,我有一个问题
h x = x : (h x)
g xs = [head xs, head xs - 1]
假设语义是按名称调用和按值调用,运行g(h 2)有什么结果?
让我们逐步进行。
首先,h x = x : (h x)
是递归的。函数h
是根据其自身定义的:给定一些x
会将其放在list
上,该x : x : x : ...
是无限的。换句话说,由于递归从不终止,因此列表不能是有限的。但是它不会永远挂起。为什么?
因为Haskell很懒。它不会对绝对必要的表达式进行评估。在您的情况下,如果调用h 2
,则根本不会在内存中创建无限列表。为什么?
因为g
仅请求名为xs
的给定列表的前两个元素。 Haskell足够聪明,可以只在需要的时间内扩展无限列表,而不会浪费资源。通常,这是懒惰的好处。它也可以与其他表达式一起使用,不仅限于列表。
“按名称呼叫”是非记忆非严格评估策略:
h x = x : (h x)
g xs = [head xs, head xs - 1]
g (h 2) = let {xs = (h 2)} in [head xs, head xs - 1]
= [let {xs = (h 2)} in head xs, let {xs = (h 2)} in head xs - 1]
= [head (h 2), let {xs = (h 2)} in head xs - 1]
= [head (let {x = 2} in x : (h x)}), let {xs = (h 2)} in head xs - 1]
= [let {x = 2} in x, let {xs = (h 2)} in head xs - 1]
= [2, let {xs = (h 2)} in head xs - 1]
= ....
“按需拨打电话”是“ [不受限制]”,又称“懒惰”评估策略:h x = x : (h x)
g xs = [head xs, head xs - 1]
g (h 2) = let {xs = (h 2)} in [head xs, head xs - 1]
= let {xs = (2 : (h 2))} in [head xs, head xs - 1]
= let {xs = (2 : (h 2))} in [2, head xs - 1]
= ....
“按价值致电”是评估策略:strict
h x = x : (h x)
g xs = [head xs, head xs - 1]
g (h 2) = let {xs = (h 2)} in [head xs, head xs - 1]
= let {xs = (2 : (h 2))} in [head xs, head xs - 1]
= let {xs = (2 : (2 : (h 2)))} in [head xs, head xs - 1]
= let {xs = (2 : (2 : (2 : (h 2))))} in [head xs, head xs - 1]
= ....
以上所有假设都在GHCi提示符下输入g (h 2)
,因此需要用它完整打印。