为什么 :sprint 即使在我评估变量时也显示 WHNF?
Why :sprint is showing WHNF even when i evaluate the variable?
这是我正在玩的代码:
*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
简短的回答是 :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'
到我们可以 :sprint
它的 Data.Map.Map
数据结构的地步,因为还没有指定哪个 Num
和 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
这里我们看到,通过消除多态性,我们得到了预期的行为。这让我们回到 :sprint
作为一个漏洞命令:为了正确预测它的输出,它需要我们更多地了解我们认为应该的值的运行时表示;它生活在多态文字、类型推断和 thunk 的交汇处,这让我们感到惊讶。
这是我正在玩的代码:
*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
简短的回答是 :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'
到我们可以 :sprint
它的 Data.Map.Map
数据结构的地步,因为还没有指定哪个 Num
和 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
这里我们看到,通过消除多态性,我们得到了预期的行为。这让我们回到 :sprint
作为一个漏洞命令:为了正确预测它的输出,它需要我们更多地了解我们认为应该的值的运行时表示;它生活在多态文字、类型推断和 thunk 的交汇处,这让我们感到惊讶。