# [Haskell-cafe] State separation/combination pattern question

Ian Lynagh igloo at earth.li
Wed Jan 3 17:07:15 EST 2007

```Hi Reto,

On Thu, Dec 21, 2006 at 10:11:22PM -0800, Reto Kramer wrote:
>
> I've tried to thread the two states (StateA and StateB) using a chain
> of StateT ... StateT ..., but couldn't really make that work.

That is how I would write it; I have attached code for your example.

> It
> seems rather arbitrary in this case which state to make the inner/
> outer one

The choice is indeed arbitrary.

> and depending on this ordering the "lifts" have to go with
> one or the other set of store calls.

If you don't mind turning on overlapping and undecidable instances then
you don't need to manually lift things at all.

Thanks
Ian

-------------- next part --------------

{-# OPTIONS_GHC -fglasgow-exts
-fallow-overlapping-instances
-fallow-undecidable-instances #-}

import Control.Monad.State (StateT, evalStateT, get, put, lift)

-- StateA

type StateA = [Integer]

getA :: m StateA
putA :: StateA -> m ()

getA = lift getA
putA = lift . putA

evalAT :: Monad m => MonadAT m a -> StateA -> m a
evalAT (MonadAT x) = evalStateT x

-- StateB

type StateB = [Integer]

getB :: m StateB
putB :: StateB -> m ()

getB = lift getB
putB = lift . putB

evalBT :: Monad m => MonadBT m a -> StateB -> m a
evalBT (MonadBT x) = evalStateT x

-- The program

main :: IO ()
main = do res <- evalAT (evalBT exec []) []
print res

exec = do foo
bar
foo
foo
bar
a <- getA
b <- getB
return (a, b)

foo :: MonadA m => m ()
foo = do st <- getA
putA (1 : st)

bar :: MonadB m => m ()
bar = do st <- getB
putB (2 : st)

```