观察哈斯克尔的懒惰

时间:2013-11-22 08:23:50

标签: haskell lazy-evaluation

是否可以编写一个Haskell函数,该函数取决于值是已经计算还是是thunk?例如。如果lazyShow :: [Int] -> String显示thunks为?且计算值正常,则在GHCi中我们会看到

> let nats = [0..]

> lazyShow nats
0 : ?

> nats !! 5    
5

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

2 个答案:

答案 0 :(得分:15)

显然,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文档中所建议的那样)来清理视图。

答案 1 :(得分:5)

您可能有兴趣挖掘"的实施:sprint"在GHCi,它有能力研究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,_,_,_,_,_]