gpt4 book ai didi

haskell - 调试不需要的严格性?

转载 作者:行者123 更新时间:2023-12-04 02:10:21 25 4
gpt4 key购买 nike

我有一个问题,我不知道如何推理。我正要问是否有人可以帮助我解决具体问题,但我突然意识到我可以问一个更笼统的问题,并希望因此得到更好的总体理解。希望。所以这里是:

当您的程序太懒惰时,这通常很明显,因为您最终会遇到诸如空间泄漏之类的明显问题。我有相反的问题:我的程序太严格了。我正在尝试 tie knots ,并发现我尝试做的某些事情会以某种方式战胜我需要的懒惰。所以我的一般问题是,如何调试不需要的严格性?

为了完整起见,这是我的具体情况:我在 RWS ,其中作者组件填充 map ,阅读器组件观察该 map 的最终状态。在完成填充之前,我不能对这张 map 做任何严格的事情。在 map 中查找值似乎没有问题,例如:

do
m <- ask
val <- m ! key
doSomething val -- etc.

但是 (!)使用 error 失败,我宁愿使用我的 monad 的 fail 失败.所以我想做如下的事情:
do
m <- ask
maybe
(fail "oh noes")
(doSomething)
(lookup key m)

这导致我的程序 <<loop>> ,我不明白。在我看来,这似乎不应该比使用 (!) 更严格。 ,但显然我错了......

最佳答案

您的第一个示例在 map 中是严格的。以下查找print "1" ,然后运行它,程序实际打印 1。当然,这需要计算 m .

main = do let m = Map.fromList [(1, print "1")]
val <- m ! 1
return val

你可能打算写一些只读取 map 的东西。以下不严格,因为 val不在 case 表达式中使用。
main = do let m = Map.fromList [(1, print "1")]
let val = m ! 1
return val

您的第二个示例是严格的,因为它检查 lookup 的结果是否成功以决定如何完成执行 block 。这需要阅读 map 。它相当于:
do m <- ask
case lookup key m of
Nothing -> fail "oh noes"
Just x -> doSomething x

调试严格性问题

评估总是由 case 表达式或某些内置运算符(如 +)强制执行。对于整数。如果你怀疑你的程序失败是因为一个值在它可用之前就被强制了,你会想知道哪个值被强制了,它在哪里被强制了。

哪个值是强制的?

在这种错误中,程序尝试评估取决于其自身评估结果的表达式。您可以使用 trace跟踪正在评估哪个表达式。在这个问题中, m 的值看起来像是强制的,所以使用 trace在评估之前打印一条消息:
do m1 <- ask
let m = trace "Using m" m1
...

如果“使用 m”是您程序的最后一个输出(在 <<loop>> 之前),那么您离错误越来越近了。如果它不在输出中,则 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)

如果您在输出中看到“Using m”后跟“Used m”,那么您知道 m 的评估。完成,程序继续运行。如果您只看到“使用 m”,则程序在这些点之间停止。在这种特殊情况下,您不应该看到“Used m”,因为 maybem 进行强制评估并导致 <<loop>> .

关于haskell - 调试不需要的严格性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11372076/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com