【发布时间】:2014-12-29 07:45:42
【问题描述】:
我试图更好地理解 Haskell 的惰性,例如当它评估函数的参数时。
来自source:
但是当对
const的调用被求值时(这是我们感兴趣的情况,毕竟这里),它的返回值也被求值......这是一个很好的一般原则:一个函数显然是严格的它的返回值,因为当需要评估函数应用程序时,它需要在函数体中评估返回的内容。从那里开始,您可以通过查看返回值始终依赖的内容来了解必须评估的内容。你的函数在这些参数上是严格的,而在其他参数上是惰性的。
所以 Haskell 中的函数总是计算自己的返回值?如果我有:
foo :: Num a => [a] -> [a]
foo [] = []
foo (_:xs) = map (* 2) xs
head (foo [1..]) -- = 4
根据上面的段落,map (* 2) xs,必须被评估。直观地说,我认为这意味着将 map 应用于整个列表 - 导致无限循环。
但是,我可以成功地拿下结果。我知道 : 在 Haskell 中是懒惰的,所以这是否意味着评估 map (* 2) xs 只是意味着构建其他尚未完全评估的东西?
对应用于无限列表的函数求值是什么意思?如果函数的返回值总是在函数被求值时被求值,那么函数真的可以返回一个 thunk 吗?
编辑:
bar x y = x
var = bar (product [1..]) 1
此代码不会挂起。当我创建var 时,它不会评估它的主体吗?还是将bar 设置为product [1..] 而不对其进行评估?如果是后者,bar 不会在 WHNF 中返回其主体,对,那么它真的“评估”了 x 吗?如果 bar 不挂在计算 product [1..] 上,bar 怎么可能对 x 严格?
【问题讨论】:
-
@AndrewC 答案(通常)是肯定的。这当然是 ghc 的答案。 foo 函数不返回 thunk。
-
@AndrewC 当我们谈论 Haskell 时,“评估”几乎总是意味着“评估到 WHNF”。否则我们会说“全面评估”之类的。
-
@augustss:
foo x y = x在 x 中是严格的,并且(可能)即使在-O0也不会返回 thunk,但一般情况下并非如此。正如您所说,有必要查看如何要求返回值。 -
函数
foo x y = x在x中是绝对严格的。严格具有数学定义并且独立于实现。