观察哈斯克尔的懒惰

是否有可能编写一个Haskell函数,取决于值是已经计算好还是为thunk? 例如,如果lazyShow :: [Int] -> String显示thunk为? 并通常计算值,在GHCi中我们会看到

> let nats = [0..]

> lazyShow nats
0 : ?

> nats !! 5    
5

> lazyShow nats
0 : 1 : 2 : 3 : 4 : ? 

显然, lazyShow不能拥有你lazyShow的类型。 如果字符串应该取决于当前的评估状态,那么IO String就是您所期望的最好的结果。

如果你感兴趣的是使用它来进行调试,那么我认为ghc-heap-view软件包(以及可能的图形前端,如ghc-vis)对于此目的很有用。 它定义了GHCi命令:printHeap ,可用于显示GHC堆中值的外观。 这可能比您想要的要低一点,但更好地理解懒惰评估和共享如何工作会非常有用:

Prelude> let nats = [0..]
Prelude> :printHeap nats
(_bco (D:Enum _fun _fun _fun _fun _fun _fun _fun _fun) _fun)()
Prelude> null nats
False
Prelude> System.Mem.performGC
Prelude> :printHeap nats
let x1 = S# 0
in x1 : _thunk x1 (S# 1)
Prelude> nats !! 5
5
Prelude> System.Mem.performGC
Prelude> :printHeap nats
let x1 = S# 5
in S# 0 : S# 1 : S# 2 : S# 3 : S# 4 : x1 : _thunk x1 (S# 1)

我通过System.Mem.performGC显式调用垃圾收集器(正如ghc-heap-view文档中的建议),以清理视图。


您可能有兴趣在GHCi中挖掘“:sprint”的实现,它可以查看thunk:

> let a = map (+1) [1..10]
> :sprint a
a = _

> length a
10

> :sprint a
a = [_,_,_,_,_,_,_,_,_,_]

> take 5 a
[2,3,4,5,6]

> :sprint a
a = [2,3,4,5,6,_,_,_,_,_]
链接地址: http://www.djcxy.com/p/43017.html

上一篇: Observing lazyness in Haskell

下一篇: What's wrong with using Identity monad with mmultP when using repa?