The problem is that you are using your own Sum
type and Monoid
type class with an operator <>
that is not the same function as your version of mappend
. If you were to enter this program in a multi-line GHCi prompt:
> :{ Prelude| ...paste your program in here... Prelude| :} >
and then try this instead:
> Sum 5 `mappend` Sum 6 `mappend` Sum 7 Sum 5 `mappend` Sum 6 `mappend` Sum 7 :: Num a => Sum a
there would be no error. If you added a deriving (Show)
to your Sum
type, you'd even get the answer you're looking for!
Ok, modules loaded: none. λ> :{ Prelude| class Monoid a where Prelude| mempty :: a Prelude| mappend :: a -> a -> a Prelude| mconcat :: [a] -> a Prelude| mconcat = foldr mappend mempty Prelude| newtype Sum a = Sum { getSum :: a } deriving (Show) Prelude| instance Num a => Monoid (Sum a) where Prelude| mempty = Sum 0 Prelude| Sum x `mappend` Sum y = Sum (x + y) Prelude| :} λ> Sum 5 `mappend` Sum 6 `mappend` Sum 7 Sum {getSum = 18} λ>
The rules for overriding library definitions in GHCi can be a little complicated, so it might be a better idea to put this into a xxx.hs
file and load it into GHCi with :l xxx.hs
for testing. If you'd tried to load this program as a xxx.hs
file, you would have gotten much clearer messages about the problem:
MonoidExample2.hs:7:19-24: error: Ambiguous occurrence ‘Monoid’ It could refer to either ‘Prelude.Monoid’, imported from ‘Prelude’ at MonoidExample2.hs:1:1 (and originally defined in ‘GHC.Base’) or ‘Main.Monoid’, defined at MonoidExample2.hs:1:1
Then, you could use the special import Prelude
syntax to hide the library definitions you didn't want. The following version works as a self-contained program:
import Prelude hiding (Monoid, mempty, mappend, mconcat, (<>)) class Monoid a where mempty :: a mappend :: a -> a -> a mconcat :: [a] -> a mconcat = foldr mappend mempty newtype Sum a = Sum { getSum :: a } deriving (Show) instance Num a => Monoid (Sum a) where mempty = Sum 0 Sum x `mappend` Sum y = Sum (x + y) (<>) :: Monoid a => a -> a -> a (<>) = mappend main :: IO () main = print $ Sum 5 <> Sum 6 <> Sum 10
Semigroup
typeclass was added (hackage.haskell.org/package/base-4.14.0.0/docs/…), and each instance of aMonoid
should be an instance ofSemigroup
as well.class Monoid
and importingData.Monoid
? Note the book usesmappend
and you use<>
.