I am building some product monads from Control.Monad.Product package. For reference, the product monad type is:
newtype Product g h a = Product { runProduct :: (g a, h a) }
Its monad instance is:
instance (Monad g, Monad h) => Monad (Product g h) where
return a = Product (return a, return a)
Product (g, h) >>= k = Product (g >>= fst . runProduct . k, h >>= snd . runProduct . k)
Product (ga, ha) >> Product (gb, hb) = Product (ga >> gb, ha >> hb)
Problem I
I build a simple monad that is a product of two State Int
Monads, However, when I try to access the underlying state next:
ss :: Product (State Int) (State Int) Int
ss = do
let (a,b) = unp $ P.Product (get,get) :: (State Int Int,State Int Int)
return 404
You see get
just creates another State Int Int
, and I am not sure how to actually get the value of the underlying state, how might I do that? Note I could potentially runState
a
and b
to get the underlying value, but this solution doesn't seem very useful since the two states' initial values must be fixed a priori.
Question II.
I would really like to be able to create a product monad over states of different types, ie:
ss2 :: Product (State Int) (State String) ()
ss2 = do
let (a,b) = unp $ P.Product (get,get) :: (State Int Int,State Int String)
return ()
But I get this type error:
Couldn't match expected type `String' with actual type `Int'
Expected type: (State Int Int, State String String)
Actual type: (StateT Int Identity Int,
StateT String Identity Int)
Because I presume the two get
must return the same type, which is an unfortunate restriction. Any thoughts on how to get around this?