2012年11月22日星期四

IO对Haskell Heap求值

这是对Edward Z. YangHaskell Heap系列的翻译。
感谢Edward的无私奉献,允许我对这些文章进行翻译。
Edward以Creative Commons Attribution-ShareAlike 3.0 Unported License对文章进行了授权,所以译文也以此License发布。 



--------------------------------------------------------------------------------

                IO对Haskell Heap求值    

原文地址为:http://blog.ezyang.com/2011/04/io-evaluates-the-haskell-heap/  

第一次看到这个系列吗?那么请从头开始看。

在今天的文章中,我们关注于——这个之前被忽略的,植根于Haskell heap周围来打开礼物的人。归根结底,Haskell heap上的礼物不会自发地打开自己。
必须有人来打开第一个礼物。
如果Haskell heap不和外面的世界交互,那么也就没有礼物需要被打开:因此IO函数就是那些会打开礼物的家伙。它们将打开哪些礼物?这个对于很多函数来说可不是那么明显的,所以我们将聚焦于一个打开礼物行为特别明显函数:evaluate。它告诉你去...
打开一个礼物。

如果你得到一个基本值,那么就结束了。但是,当然,你可能得到了一个礼物卡(constructor):
你会打开剩下的礼物吗?尽管你心中非常不满,但是答案是。evaluate只让你打开一个礼物。如果礼物已经打开了,那么没什么事再需要你做了。

进一步提示:如果你想对更多的东西求值,就做一个礼物,该礼物里有能为你打开那些东西的幽灵!当论及lazy IO时,这种做法一个常用的例子是:evaluate (length xs),如果你不太明白的话,不要担心:我实际上还没说明我们如何制作礼物!
即使我们仅仅正在打开一个礼物,很多事情也会发生,就像上一篇文章中提及的。它会执行一些IO...

当求值进行时,我们能直窥求值的窗口是(译注:让鬼魂喊一声):当我们正常运行程序时,我们看不到正在打开的礼物;但是如果我们让鬼魂在它被打扰时也大声喊一下,我们就能拿回这个信息。实际上,这就是Debug.Trace做的事!

还有别的方法可以看到evaluation如何进行的(译注:作者没说别的方法是什么)。礼物可能会爆炸(译注:这里话题转变的很突然啊):这种礼物是会爆炸的诱饵礼物,也被称为“bottom”(译注:bottom指符号⊥,在Haskell中, ⊥是一个占位符,表明计算不会成功。比如无穷循环,或者调用error,或者特殊值undefined)。
爆炸可能是由于undefined或者error "Foobar"引起的。
爆了。


结束前我们来看一个实践中使用的方法。正如我们提到的,你只有明确地通过IO打开礼物时才能确定礼物是否已经被打开了。否则,鬼魂可能会和逗你玩。毕竟你不可能真的看到Haskell heap,所以没有方法能直接告诉你一个礼物是否已经被打开了。
如果你不确定一个thunk何时会被求值,那么给它加一个跟踪语句。要是鬼魂躲在你背后偷懒,那么跟踪语句就没什么显示。
更常见的情况是,虽然跟踪语句会显示信息,但是可能比你预期的晚(鬼魂也许很懒,但是它们最终会完成工作)。所以提前结束你的程序(译注:在跟踪信息显示之前)或者增加额外的打印语句来为你的程序定界是很有用的。

上一篇:Haskell Heap上的求值
下一篇:用Python实现Haskell Heap,第1版

技术注释:和我之前所说的不同,没有理论上的理由来限制我们自发地对heap上的thunk求值:这种求值方式称为:speculative evaluation(译注:推断求值,一种性能优化技术,在还不知道是否该求值时提前求值,以此来减少知道是否该求值时再去求值引起的延迟。)。有点混乱的是,IO actions自身也可以是thunks:这相当于传递IO a的值而不实际地“运行”它们。但是,既然我不是在这里讨论monads,我将简单忽略礼物中包含IO actions的情况——它们工作方式是一样的,但是你必须保持间接层次清晰(but you have to keep the levels of indirection straight.)。最后,无穷循环当然算是bottom,但是为了余下的无穷而打开一个礼物的场景可没有打开一个爆炸礼物时那么剧烈。

没有评论:

发表评论