当参数是列表时,惰性求值如何工作?

时间:2018-06-18 10:10:47

标签: haskell lazy-evaluation

根据我的理解,延迟评估是在将参数传递给函数之前不对其进行求值,但仅在它们的值实际使用时才进行求值。

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

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

doubleMe(doubleMe(doubleMe(xs)))

作者说,命令式语言可能会通过列表一次并复制然后返回。然后它将再次通过列表两次并返回结果。

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

doubleMe(doubleMe(doubleMe(1)))

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

所以只有当你确实需要它时,才能通过列表。

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

1 个答案:

答案 0 :(得分:6)

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

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

1:1+1:[]

所有Haskell列表都是链表,这意味着它们有 head tail 。在上面的示例中,头部为1,尾部为1+1:[]

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

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

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

这就是懒惰评估列表的方式。 1+1仍然是 thunk (未评估的表达式),直到需要该值。