Jake Matthews
Jake Matthews

Reputation: 115

How to print the result of a State Monad in Haskell?

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

Answers (3)

liminalisht
liminalisht

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

hao
hao

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

Daniel Wagner
Daniel Wagner

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

Related Questions