Search code examples
haskellmonadsmonad-transformerswriter-monad

Writer Monad Nested Twice


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?


Solution

  • 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