This gist and its comments are a way of working through an exercise problem found in Chapter 15 of the Haskell Book.
Here's the code from the exercise. Our job is to implement the mempty
and mappend
functions, which are presented here as undefined
:
module Chap15Ex where
import Data.Monoid
newtype Mem s a =
Mem {
runMem :: s -> (a, s)
}
instance Monoid a => Monoid (Mem s a) where
mempty = undefined
mappend = undefined
f' :: Mem Integer String
f' = Mem $ \s -> ("hi", s + 1)
main = do
let rmzero = runMem mempty 0
rmleft = runMem (f' <> mempty) 0
rmright = runMem (mempty <> f') 0
print $ rmleft -- ("hi, 1)
print $ rmright -- ("hi", 1)
print $ (rmzero :: (String, Int)) -- ("", 0)
print $ rmleft == runMem f' 0 -- True
print $ rmright == runMem f' 0 -- True
My first question is about implementing
mempty
, since this seems like a logical place to start.Our
Mem
type ultimately stores a tuple of(a, s)
, wherea
ands
could be different types. So when we're talking about what identity looks like for both those types, it seems to me like we should delegate to the type itself:... except I don't think that works, because we've specified in our instance declaration that only
a
needs to have an instance ofMonoid
.