根据我的理解,延迟评估是在将参数传递给函数之前不对其进行求值,但仅在它们的值实际使用时才进行求值。
但是在haskell教程中,我看到了一个例子。
xs = [1,2,3,4,5,6,7,8]
doubleMe(doubleMe(doubleMe(xs)))
作者说,命令式语言可能会通过列表一次并复制然后返回。然后它将再次通过列表两次并返回结果。
但是在懒惰的语言中,它会首先计算
doubleMe(doubleMe(doubleMe(1)))
这将返回doubleMe(1)
,即2
。然后是4
,最后是8
。
所以只有当你确实需要它时,才能通过列表。
这让我很困惑。懒惰语言为什么不把整个列表作为一个整体,但拆分呢?我的意思是我们可以在使用它之前忽略列表或表达式。但是我们需要在使用它时评估整个事情,不是吗?
答案 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 (未评估的表达式),直到需要该值。