そのため、私は State Monad を構築していましたが、デバッグを困難にしているその怠惰な性質に関するいくつかの問題に遭遇しました。
私の State モナドは、値のリストを取得し、それらを 1 つずつ状態の一部にプッシュすることによって動作します。次に、状態の他の部分を生成するために、各値の後に状態にある値を分析します。
デバッグが難しい理由を説明するために、この簡単な例を思いつきました。
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,"
しかし、最終結果は同じです。より自然にシーケンシャルになるように、デバッグ時に状態モナドの遅延を処理するより良い方法はありますか?