Summary: While using Writer monad, I would like to be able to switch between 2 different versions of mappend
without losing the state.
I use two boolean flags to track some state:
data Flags = F Bool Bool
Now I define two Monoid
instances which differ in a way they combine the flags in mappend
:
newtype XFlags = XF Flags
instance Monoid XFlags where
mempty = XF (F True False)
(XF (F s0 c0)) `mappend` (XF (F s1 c1)) = XF (F (s0 && s1)
(c0 || c1 || not (s0 || s1)))
newtype SFlags = SF Flags
instance Monoid SFlags where
mempty = SF (F True False)
(SF (F s0 c0)) `mappend` (SF (F s1 c1)) = SF (F (s0 && s1) (c0 || c1))
Now I can have 2 Writer monads with different flags handling:
type XInt = WriterT XFlags Identity Int
type SInt = WriterT SFlags Identity Int
Now I can have operations like:
xplus :: XInt -> XInt -> XInt
xplus = liftM2 (+)
splus :: SInt -> SInt -> SInt
splus = liftM2 (+)
Now to I would like to build expressions like:
foo = splus (return 1) (xplus (return 2) (return 3))
To do so I need to be able to convert between the two without losing any flags and preferably without unwrapping the monad (using runWriter
). This part I have not been figure out. It looks little bit like I can try to nest Writers using monad transformer but I am not sure if it is applicable directly here. I will appreciate some guidance on the best way to implement something like this.