Дальнейшие проблемы с классом типа моноид - PullRequest
0 голосов
/ 11 июля 2020

Я пытаюсь поиграть с моноидами, используя класс типов Semigroup, и я пытаюсь определить моноид на натуральных числах. Я помещаю следующие объявления классов и экземпляров в 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| :} 

Я получаю сообщение:

<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

Затем я ввел import qualified Prelude as P, чтобы избежать cla sh, но это не работает, и я получаю сообщение об ошибке:

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) 

1 Ответ

4 голосов
/ 11 июля 2020

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