Reputation: 115
Is it possible to print the result of a state monad in Haskell?
I'm trying to understand state monads and in a book I have been following supplies the code below for creating a state monad, but I am struggling with this topic as I am unable to view the process visually i.e. see the end result.
newtype State s a = State { runState :: s -> (a,s)}
instance Monad (State s) where
return x = State $ \s -> (x,s)
(State h) >>= f = State $ \s -> let (a, newState) = h s
(State g) = f a
in g newState
Upvotes: 0
Views: 1684
Reputation: 1253
The code you've supplied defines the kind of thing State s a
is. And it also says that State s
is a monad - that is, the kind of thing State s
is conforms to the Monad
typeclass/interface. This means you can bind one State s
computation to another (as long as the type s
is the same in each).
So your situation is analogous to that of someone who has defined the kind of thing that a Map
is, and has also written code that says a Map
conforms to such and such interfaces, but who doesn't have any maps, and hasn't yet run any computation with them. There's nothing to print then.
I take it you want to see the result of evaluating or executing your state actions, but you have not defined any actual state actions yet, nor have you called runState
(or evalState
or execState
) on them. Don't forget you also need to supply an initial state to run the computation.
So maybe start by letting s
and a
be some particular types. E.g. let s
be Int
and let a
be Int
. Now you could go write some fns, e.g. f :: Int -> (Int, Int)
, and g :: Int -> (Int, Int)
. Maybe one function decrements the state, returning the new state and value, and another function increments the state, returning the new state and value. Then you could make a State Int Int
out of f
by wrapping it in the State
constructor. And you could use >>=
to chain as many state actions together as you like. Finally, you can use runState
on this, to get the resulting value and resulting state, as long as you also supply an initial state (e.g. 0).
Upvotes: 3
Reputation: 10238
If it's just the result you want, and if you're just debugging:
import Debug.Trace
import Control.Monad.Trans.State
action :: State [Int] ()
action = do
put [0]
modify (1:)
modify (2:)
get >>= traceShowM
modify (3:)
modify (4:)
get >>= traceShowM
Upvotes: 1
Reputation: 153172
It is generally not possible to print functions in a meaningful way. If the domain of the function is small, you can import Data.Universe.Instances.Show
from the universe-reverse-instances package to get a Show
instance that prints a lookup table that is semantically equivalent to the function. With that module imported, you could simply add deriving Show
to your newtype
declaration to be able to print State
actions over small state spaces.
Upvotes: 4