Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

printing state value for debugging

How can we print current state value, for debugging purposes? E.g., in code from concrete-example-1 of http://www.haskell.org/haskellwiki/State_Monad , how can we print the current state value after each input character is read?

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
like image 571
R71 Avatar asked Jan 18 '23 16:01

R71


2 Answers

For quick and dirty debugging, use trace from Debug.Trace. I often find it useful to flip the argument order and define

infixl 0 `debug`

debug :: a -> String -> a
debug = flip trace

Then you can tack the debugging to the end of the line and it's easier to comment out (and at the end remove).

For more principled logging, combine the State with a Writer and tell the logging messages or use StateT s IO if you directly want to log to a file or stderr.

like image 198
Daniel Fischer Avatar answered Jan 24 '23 19:01

Daniel Fischer


As n.m. points out there is Debug.Trace, but it's easy to write something yourself. However I strongly recommend to use this only for debugging, and to remove it for real world code. Here is an example:

import System.IO.Unsafe

output a b = seq (unsafePerformIO (print a))  b

(output "test" 23) * 25
-- "test"
-- 527

Here output takes an argument to print out, and a return value, behaving like a const, just with a side effect. seq is needed to force the evaluation of print, else laziness will prevent to print anything.

like image 42
Landei Avatar answered Jan 24 '23 20:01

Landei