这是我正在玩的代码:
*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
答案 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'
我们可以:sprint
其Data.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的交叉点而让我们感到惊讶。