【发布时间】:2015-04-02 21:19:25
【问题描述】:
考虑这个将列表中所有元素加倍的函数:
doubleMe [] = []
doubleMe (x:xs) = (2*x):(doubleMe xs)
然后考虑表达式
doubleMe (doubleMe [a,b,c])
很明显,在运行时,这首先扩展为:
doubleMe ( (2*a):(doubleMe [b,c]) )
(这很明显,因为据我所知不存在其他可能性)。
但我的问题是:为什么现在会扩展到
2*(2*a) : doubleMe( doubleMe [b,c] )
而不是
doubleMe( (2*a):( (2*b) : doubleMe [c] ) )
?
直觉上,我知道答案:因为 Haskell 很懒。但是谁能给我一个更准确的答案?
列表是否有什么特别之处会导致这种情况,或者这个想法是否比列表更普遍?
【问题讨论】:
-
第二次展开会出现类型错误,因为您将数字和列表相乘。
-
不完全是一个精确的答案,但直觉上对
doubleMe的最外部调用将首先扩展,而不是内部调用。 -
@DavidYoung 谢谢,错字已修正。
-
我想你想从可简化表达式(redex)的角度来看待这个问题。 Here is a short introduction。基本上,redex 是可以使用函数重写的任何东西(如
doubleMe (x:xs) -> 2*x : doubleMe xs)——这对于列表来说并不特殊。 “惰性”评估恰恰意味着您首先评估最外层(有时称为“最左侧”)的 redex,这似乎是您直觉上认为的“惰性评估”。 -
非常感谢你写出这样一个格式良好的问题。我什至不了解 Haskell,发现这(以及很好的答案)是一本有趣的书。
标签: haskell