当参数是列表时惰性评估如何工作?

How does lazy evaluation works when the argument is a list?

根据我的理解,惰性评估是在将参数传递给函数之前不对其进行评估,而仅在实际使用其值时进行评估。

但是在 haskell 教程中,我看到了一个示例。

xs = [1,2,3,4,5,6,7,8] 

doubleMe(doubleMe(doubleMe(xs)))

作者说命令式语言可能会遍历一次列表并制作副本,然后 return 它。然后它会再通过列表两次并 return 结果。

但是在惰性语言中,它会首先计算

doubleMe(doubleMe(doubleMe(1)))

这将返回一个doubleMe(1),即2。然后是4,最后是8.

所以它只会在列表中传递一个,并且只有在您真正需要它时才会传递。

这让我很困惑。懒惰的语言为什么不把列表作为一个整体,而是拆分呢?我的意思是我们可以在使用列表或表达式之前忽略它。但是我们在使用的时候需要对整个东西进行评估,不是吗?

[1,2,3,4,5,6,7,8] 这样的列表只是语法糖:1:2:3:4:5:6:7:8:[].

在这种情况下,列表中的所有值都是数字常量,但我们可以定义另一个更小的列表,如下所示:

1:1+1:[]

所有Haskell列表都是链表,这意味着它们有一个和一个。在上面的例子中,头部是1,尾部是1+1:[].

如果您只想要列表的头部,则没有理由评估列表的其余部分:

(h:_) = 1:1+1:[]

这里的h指的是1。如果您只需要 h,则没有理由评估列表的其余部分 (1+1:[])。

这就是延迟计算列表的方式。 1+1 仍然是 thunk(未计算的表达式),直到需要该值。