[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.Trans (MonadTrans)
import Control.Monad.State (StateT, evalStateT, get, put, lift)
-- StateA
type StateA = [Integer]
newtype MonadAT m a = MonadAT (StateT StateA m a)
deriving (Monad, MonadTrans)
class Monad m => MonadA m where
getA :: m StateA
putA :: StateA -> m ()
instance Monad m => MonadA (MonadAT m) where
getA = MonadAT get
putA = MonadAT . put
instance (MonadTrans t, MonadA m, Monad (t m)) => MonadA (t m) where
getA = lift getA
putA = lift . putA
evalAT :: Monad m => MonadAT m a -> StateA -> m a
evalAT (MonadAT x) = evalStateT x
-- StateB
type StateB = [Integer]
newtype MonadBT m a = MonadBT (StateT StateB m a)
deriving (Monad, MonadTrans)
class Monad m => MonadB m where
getB :: m StateB
putB :: StateB -> m ()
instance Monad m => MonadB (MonadBT m) where
getB = MonadBT get
putB = MonadBT . put
instance (MonadTrans t, MonadB m, Monad (t m)) => MonadB (t m) where
getB = lift getB
putB = lift . putB
evalBT :: Monad m => MonadBT m a -> StateB -> m a
evalBT (MonadBT x) = evalStateT x
-- The program
type Monads = MonadBT (MonadAT IO)
main :: IO ()
main = do res <- evalAT (evalBT exec []) []
print res
exec :: Monads (StateA, StateB)
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)
More information about the Haskell-Cafe
mailing list