为什么:即使我评估变量,sprint也会显示WHNF?

时间:2016-11-20 09:13:34

标签: debugging haskell ghci

这是我正在玩的代码:

*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG> let x = Data.Map.empty
*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG> let y = Data.Map.insert 1 (1+1,"ashish") x
*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG> :sprint x
x = containers-0.5.7.1:Data.Map.Base.Tip
*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG> :sprint y
y = _
*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG> y == x
False
*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG> :sprint y
y = _
*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG> seq y y
fromList [(1,(2,"ashish"))]
*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG> :sprint y
y = _
*Main DepthFirstSearch DivideAndConquer Fibonacci LongestEdgePathInDAG>

我无法理解为什么:sprint y始终显示_

我有

➜  hsalgos git:(master) ✗ stack --version
Version 1.1.2 x86_64 hpack-0.14.0
➜  hsalgos git:(master) ✗

ghc 7.10.3

1 个答案:

答案 0 :(得分:4)

简短的回答是:sprint漏洞。

答案很长,因为您的y值是多态的:

λ> let y = insert 1 (1 + 1, "str") empty
λ> :t y
y :: (Num k, Num t, Ord k) => Map k (t, [Char])

在这种情况下,seq y ()将无法评估到地图。想象一下y的类型,因为运行时代表它:y' :: NumDict k -> NumDict t -> OrdDict k -> Map k (t, String)seq y' ()无法评估y'我们可以:sprintData.Map.Map数据结构,因为还没有指定Num和{{1}我们想要的实例。

作为反例:

Ord

在这里,我们看到通过消除多态性,我们得到了预期的行为。这使我们回到λ> let y = insert 1 (1 + 1, "str") empty :: Map Int (Int, String) λ> :t y y :: Map Int (Int, String) λ> :sprint y y = _ λ> seq y () () λ> :sprint y y = containers-0.5.6.2:Data.Map.Base.Bin 1 1 (_,_) containers-0.5.6.2:Data.Map.Base.Tip containers-0.5.6.2:Data.Map.Base.Tip 作为泄漏命令:要正确预测其输出,它需要我们更多地了解我们认为应该的值的运行时表示;它通过生活在多态文字,类型推理和thunk的交叉点而让我们感到惊讶。