Reputation: 45
I took code from this lecture, but I got an error with the demo code below:
newtype Sum a = Sum a
deriving (Eq,Ord,Show)
getSum::Sum a -> a
getSum (Sum a) = a
instance Num a=>Monoid (Sum a)where
mempty = Sum 0
mappend = (+)
newtype Product a = Product a
deriving (Eq,Ord,Show)
getProduct ::Product a -> a
getProduct (Product a ) = a
instance Num a => Monoid (Product a ) where
mempty = Product 1
mappend = (*)
I got the following error message (with GHC 8.2.2):
Test.hs:40:13: error:
? Could not deduce (Num (Sum a)) arising from a use of ‘+’
from the context: Num a
bound by the instance declaration at Test.hs:38:10-30
? In the expression: (+)
In an equation for ‘mappend’: mappend = (+)
In the instance declaration for ‘Monoid (Sum a)’
| 40 | mappend = (+)
Test.hs:50:13: error:
? Could not deduce (Num (Product a)) arising from a use of ‘*’
from the context: Num a
bound by the instance declaration at Test.hs:48:10-37
? In the expression: (*)
In an equation for ‘mappend’: mappend = (*)
In the instance declaration for ‘Monoid (Product a)’
50 | mappend = (*)
Upvotes: 0
Views: 209
Reputation: 54213
By defining mappend
as (+)
, you're saying that Sum a
is itself a member of Num
. Rather, it only contains those members, so (+)
should operate on those members.
instance Num a => Monoid (Sum a) where
mempty = Sum 0
mappend (Sum x) (Sum y) = Sum $ x + y
Likewise for Product
instance Num a => Monoid (Product a) where
mempty = Product 1
mappend (Product x) (Product y) = Product $ x * y
Then your monoid instances work as expected.
xs = map Sum [1..5]
ys = map Product [1..5]
mconcat xs -- 15
mconcat ys -- 120
Alternatively you could follow the lecture's code and derive Num
in your newtypes.
-- from the linked lecture
newtype Sum a = Sum a
deriving (Eq, Ord, Num, Show)
newtype Product a = Product a
deriving (Eq, Ord, Num, Show)
Upvotes: 3