As a part of self-learning exercise in Haskell, I am trying to derive a Monad
instance for my type. The type is defined as:
newtype ParsePackUnpack f a = ParsePackUnpack
{
unparse:: State PackUnpackState (Ap f a)
}
where Ap f a
comes from Data.Monoid
. With my type, I'm trying to say that parsing is a stateful operation with the result being any monoid
.
So far, I have been successful in implementing Functor
and Applicative
instances for this 3 level deep type by lifting:
instance Functor f => Functor (ParsePackUnpack f) where
fmap f ma =
let f' = fmap f -- lift (a -> b) to (Ap f a -> Ap f b)
in ParsePackUnpack $ f' <$> (unparse ma)
instance Applicative f => Applicative (ParsePackUnpack f) where
pure = ParsePackUnpack . pure . pure
f <*> ma =
let f' = liftA2 (<*>) . unparse $ f -- lift Ap f (a -> b) -> Ap f a -> Ap f b to State s (Ap f a) -> State s (Ap f b)
in ParsePackUnpack $ f' (unparse ma) -- Apply to State s (Ap f a)
But I could not derive a Monad instance for my type correctly. After some type-golfing, this is my latest attempt:
instance Monad f => Monad (ParsePackUnpack f) where
return = ParsePackUnpack . return . return
ma >>= f = ParsePackUnpack . state $ \st ->
let (a, s) = runState (unparse ma) st
res = a >>= fst . flip runState s . unparse . f -- fst ignores state from the result
in (res, s)
Which I believe is incorrect because I am ignoring the state from res
operation.
What is correct way to implement the >>=
operation for my type? As this is a learning exercise, I'm trying to avoid Monad transformers. If Monad transformers is the way to go, could you also explain why that is the case?