为了调试目的,我们如何打印当前状态值?例如,在http://www.haskell.org/haskellwiki/State_Monad的具体示例1的代码中,如何在读取每个输入字符后打印当前状态值?
module StateGame where
import Control.Monad.State
type GameValue = Int
type GameState = (Bool, Int)
playGame :: String -> State GameState GameValue
playGame [] = do
(_, score) <- get
return score
playGame (x:xs) = do
(on, score) <- get
case x of
'a' | on -> put (on, score + 1)
'b' | on -> put (on, score - 1)
'c' -> put (not on, score)
_ -> put (on, score)
playGame xs
startState = (False, 0)
main = print $ evalState (playGame "abcaaacbbcabbab") startState
答案 0 :(得分:7)
要进行快速而肮脏的调试,请使用trace
中的Debug.Trace
。我经常发现翻转参数顺序和定义
infixl 0 `debug`
debug :: a -> String -> a
debug = flip trace
然后你可以将调试添加到行尾,并且更容易注释掉(最后删除)。
对于更有原则的日志记录,请将State
与Writer
和tell
日志消息结合使用,或者如果您想直接登录文件或stderr,请使用StateT s IO
。
答案 1 :(得分:2)
早上好指出有Debug.Trace
,但你自己写一些东西很容易。但是我强烈建议仅将其用于调试,并将其删除以用于实际代码。这是一个例子:
import System.IO.Unsafe
output a b = seq (unsafePerformIO (print a)) b
(output "test" 23) * 25
-- "test"
-- 527
这里output
采用参数打印输出,返回值的行为类似于const
,只是带有副作用。强制评估seq
需要print
,否则懒惰会阻止打印任何内容。