Reputation: 705
I am trying to toy around with monoids using the Semigroup
typeclass, and I am trying to define a monoid on the natural numbers. I put the following class and instance declarations into GHCI
Prelude:{
Prelude| class Semigroup a where
Prelude| (<>) :: a -> a -> a)
Prelude| newtype Sum a = Sum { getSum :: a }
Prelude| deriving (Eq, Ord, Show)
Prelude| instance Num a => Monoid (Sum a) where
Prelude| (<>) = coerce ((+) :: a -> a -> a)
Prelude| instance Num a => Monoid (Sum a) where
Prelude| mempty = Sum 0
Prelude| :}
I receive the message:
<interactive>:7:4: error:
Ambiguous occurrence ‘<>’
It could refer to either ‘Prelude.<>’,
imported qualified from ‘Prelude’
(and originally defined in ‘GHC.Base’)
or ‘<>’, defined at <interactive>:3:4
I then entered import qualified Prelude as P
, so as to avoid the clash, but this does not work, and I get the error message:
code<interactive>:26:19: error:
Not in scope: type constructor or class ‘Monoid’
Perhaps you meant one of these:
‘P.Monoid’ (imported from Prelude),
‘P.Monad’ (imported from Prelude)
Upvotes: 0
Views: 201
Reputation: 476547
You should not define the typeclass yourself. It is already defined, by defining another one, it means that all your (<>)
functions, etc. now can point to the Semigroup
you defined, or the one that was defined in the Prelude
.
You thus can define your type and make it an instance of Semigroup
and Monoid
with:
import Data.Semigroup
newtype Sum a = Sum { getSum :: a } deriving (Eq, Ord, Show)
instance Num a => Semigroup (Sum a) where
Sum a <> Sum b = Sum (a + b)
instance Num a => Monoid (Sum a) where
mempty = Sum 0
mappend = (<>)
If we thus run this in the shell, we get:
Prelude> import Data.Semigroup
Prelude Data.Semigroup> :{
Prelude Data.Semigroup| newtype Sum a = Sum { getSum :: a } deriving (Eq, Ord, Show)
Prelude Data.Semigroup|
Prelude Data.Semigroup| instance Num a => Semigroup (Sum a) where
Prelude Data.Semigroup| Sum a <> Sum b = Sum (a + b)
Prelude Data.Semigroup|
Prelude Data.Semigroup| instance Num a => Monoid (Sum a) where
Prelude Data.Semigroup| mempty = Sum 0
Prelude Data.Semigroup| mappend = (<>)
Prelude Data.Semigroup| :}
Prelude Data.Semigroup> Sum 0 <> Sum 1 <> Sum 4 <> Sum 5
Sum {getSum = 10}
Upvotes: 4