I am trying to nest writer monad twice using Monad Transformers. Here is a sketch:
import Control.Monad.Identity
import Control.Monad.Writer
data Struct = S Bool
instance Monoid Struct where
mempty = S True
mappend (S a) (S b) = S (a && b)
data Collision = C Bool
instance Monoid Collision where
mempty = C False
mappend (C a) (C b) = C (a || b)
type CSInt = WriterT Collision (WriterT Struct Identity) Int
foo :: Int -> CSInt
foo x = do (tell (S False)) ; return x
The foo
function does not compile, as I need to use tell
on Struct
monad, not Collision
. Is it possible at all?
Having multiple similar layers is in fact one case where the mtl
approach, which is meant to make lift
implicit, has trouble as you mentionned. So you can use lift
explicitly.
lift :: Writer Struct Bool -> WriterT Collision (Writer Struct) Bool
Thus
foo x = do lift (tell (S False)) ; return x