mer*_*ict 11 haskell lazy-evaluation strictness tying-the-knot
我有一个问题,我不知道如何推理.我只是想问一下是否有人可以帮助我解决具体问题,但我突然意识到我可以提出一个更普遍的问题,希望能得到一个更好的一般性理解.希望.所以这里:
当你的程序太懒,通常很明显,因为你最终会遇到像空间泄漏这样的明显问题.我有相反的问题:我的程序太严格了.我想扎 结,并发现某些事情,我试图这样做会以某种方式打败我需要的懒惰.所以我的一般问题是,如何调试不必要的严格性?
为了完整起见,这是我的具体情况:我在RWS,编写器组件填充地图,阅读器组件观察该地图的最终状态.在我完成填充之前,我不能对这张地图做任何严格的事情.在地图中查找值似乎没有问题,例如:
do
m <- ask
val <- m ! key
doSomething val -- etc.
Run Code Online (Sandbox Code Playgroud)
但是(!)没有使用error,我更愿意使用我的monad失败fail.所以我想做类似以下的事情:
do
m <- ask
maybe
(fail "oh noes")
(doSomething)
(lookup key m)
Run Code Online (Sandbox Code Playgroud)
这导致我的程序<<loop>>,我不明白.在我看来,这不应该比使用更严格(!),但显然我错了......
Hea*_*ink 10
你的第一个例子是地图中的严格.以下查找print "1",然后运行它,程序实际打印1.当然,这需要评估m.
main = do let m = Map.fromList [(1, print "1")]
val <- m ! 1
return val
Run Code Online (Sandbox Code Playgroud)
你可能想要写一些只能读取地图的东西.以下内容并不严格,因为val在case表达式中没有使用.
main = do let m = Map.fromList [(1, print "1")]
let val = m ! 1
return val
Run Code Online (Sandbox Code Playgroud)
你的第二个例子是严格的,因为它检查是否lookup成功的结果,以决定如何完成执行块.这需要阅读地图.它相当于:
do m <- ask
case lookup key m of
Nothing -> fail "oh noes"
Just x -> doSomething x
Run Code Online (Sandbox Code Playgroud)
评估始终由案例表达式或某些内置运算符(如+整数)强制执行.如果您怀疑程序失败,因为值在可用之前被强制执行,您将需要找出强制使用哪个值以及强制使用哪个值.
在这种错误中,程序试图评估一个取决于其自身评估结果的表达式.您可以使用它trace来跟踪正在评估的表达式.在这个问题中,它看起来像是m被强制的值,所以用于trace在评估之前打印消息:
do m1 <- ask
let m = trace "Using m" m1
...
Run Code Online (Sandbox Code Playgroud)
如果"使用m"是程序的最后一个输出(在此之前<<loop>>),那么你就越接近这个bug了.如果它不在输出中,那么m就不会被评估,所以问题出在其他地方.如果输出中的这一行后面有某些内容,则程序继续执行并且稍后发生错误,因此问题必须在其他地方.
这告诉你评估在停止之前至少得到了这么远.但它走了多远?这个问题实际上发生得太晚了吗?要看到这一点,请尝试在trace以后进行评估的内容上.我们知道m评估是为了决定哪个分支的maybe运行,所以我们可以放在trace那些点上.
do m1 <- ask
let m = trace "Using m" m1
maybe (trace "Used m" $ fail "oh noes")
(\x -> trace "Used m" $ doSomething x)
(lookup key m)
Run Code Online (Sandbox Code Playgroud)
如果在输出中看到"使用m"后跟"使用过的m",那么您就知道已m完成的评估和程序继续进行.如果只看到"使用m",则程序在这些点之间停止.在这种特殊情况下,你不应该看到"使用过的m",因为maybe力量的评估m和导致了<<loop>>.
| 归档时间: |
|
| 查看次数: |
344 次 |
| 最近记录: |