Вы должны не определять класс типов самостоятельно. Он уже определен, определяя другой, это означает, что все ваши (<>)
функции, et c. теперь может указывать на Semigroup
, определенный вами , или тот, который был определен в Prelude
.
Таким образом, вы можете определить свой тип и сделать его экземпляром Semigroup
и Monoid
с:
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 = (<>)
Если мы таким образом запустим это в оболочке, мы получим:
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}