所以我正在构建一个 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,"
但最终的结果是一样的。有没有更好的方法来处理状态单子在调试中的懒惰,所以它更自然地顺序?