gpt4 book ai didi

haskell - 在调试我的 State Monad 时,根据跟踪的位置颠倒顺序

转载 作者:行者123 更新时间:2023-12-04 23:25:52 27 4
gpt4 key购买 nike

所以我在构建一个 State Monad 时遇到了一些问题,它的惰性使我很难调试。

我的 State monad 通过获取一系列值来操作,将它们一个一个地推送到状态的一部分,然后我分析每个值之后状态上的值以生成状态的另一部分。

我想出了这个简单的例子来说明为什么很难调试。

module Main where

import Control.Monad.State
import Debug.Trace

runSim :: [Int] -> State String String
runSim [] = return =<< get
runSim (cur:xs) = do
lst <- get
let val = (show $ 2*cur)
put $ trace ((show $ length lst) ++ " " ++ (show cur)) ((val) ++ "," ++ lst)
runSim xs

main :: IO ()
main = print $ evalState (runSim [1..10]) ""

这个的输出是:
0 1
2 2
4 3
6 4
8 5
11 6
14 7
17 8
20 9
23 10
"20,18,16,14,12,10,8,6,4,2,"

但是,如果我将跟踪行更改为:
put $ trace ((show cur)) ((val) ++ "," ++ lst)

输出相反:
10
9
8
7
6
5
4
3
2
1
"20,18,16,14,12,10,8,6,4,2,"

但最终结果是一样的。有没有更好的方法来处理 State Monad 在调试中的惰性,使其更自然地顺序化?

最佳答案

问题在于trace调用仅在最后进行评估。

计算构建状态(为简洁起见,仅列出两个元素)

runSim [1, 2] "" ~> ( (), state1@(trace (output 1 "") (logString 1 "")))
~> runSim [2] ( (), trace (output 2 state1) (logString2 state1))

所以在最终状态下, trace因为最后一个推送的列表元素是最外面的。

现在在第二种情况下,其中
output i _ = show i

跟踪输出不依赖于之前发生的事情,所以 trace最后推的先运行等等。

但在第一种情况下,
output i state = show (length state) ++ " " ++ show i

跟踪输出取决于状态,因此必须在打印跟踪输出之前评估状态。但是 state是调用之前推送的 trace ,因此跟踪需要先运行,等等。因此跟踪输出中的数据依赖性确保跟踪按推送顺序运行。

为确保跟踪按该顺序运行而没有数据依赖性,您必须拉取 trace呼出 put ,或力评估 put状态,
put $! trace ((show $ length lst) ++ " " ++ (show cur)) ((val) ++ "," ++ lst)

或者
trace ((show $ length lst) ++ " " ++ (show cur)) $ put ((val) ++ "," ++ lst)

关于haskell - 在调试我的 State Monad 时,根据跟踪的位置颠倒顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13126741/

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