web-dev-qa-db-fra.com

Impossible de déduire (semigroupe (facultatif a)) découlant des superclasses d'une déclaration d'instance

Le code suivant de "Programmation Haskell: à partir des premiers principes" ne parvient pas à être compilé:

module Learn where
import Data.Semigroup
import Data.Monoid

-- Exercise: Optional Monoid
data Optional a = Nada
                | Only a
                deriving (Eq, Show)

instance Monoid a => Monoid (Optional a) where
 mempty = Nada
 mappend Nada Nada = Nada
 mappend (Only a) Nada = Only $ mappend a mempty
 mappend Nada (Only a) = Only $ mappend mempty a
 mappend (Only a) (Only b) = Only $ mappend a b

Cela donne l'erreur suivante:

intermission.hs:11:10: error:
    • Could not deduce (Semigroup (Optional a))
        arising from the superclasses of an instance declaration
      from the context: Monoid a
        bound by the instance declaration at intermission.hs:11:10-40
    • In the instance declaration for ‘Monoid (Optional a)’
   |
11 | instance Monoid a => Monoid (Optional a) where
   |   

Afin d'empêcher ghc de se plaindre, j'ai dû créer une instance de semi-groupe de facultatif a et définir "<>". Cela n'a pas vraiment de sens pour moi et je me demandais s'il y avait quelque chose que j'ignorais.

7
jarvin

" NOTE: Semigroup est une superclasse de Monoid depuis base-4.11.0.0. "

La liste des super-classes en Europe évolue lentement. Au fur et à mesure que de nouvelles classes utiles sont proposées, l'API pour les classes plus anciennes est mise à jour pour refléter leurs relations. Cela a pour effet malheureux de casser l'ancien code. La base 4.11.1.0 a été publiée en avril 2018 avec ce changement radical en Monoid.

8
John F. Miller

Voici la solution:

import Data.Monoid

data Optional a = Nada | Only a deriving (Eq, Show)

instance Monoid a => Monoid (Optional a) where
   mempty = Nada

instance Semigroup a => Semigroup (Optional a) where
  Nada <> (Only a) = Only a
  (Only a) <> Nada = Only a
  (Only a) <> (Only a') = Only (a <> a')
  Nada <> Nada = Nada

main :: IO ()
main = do
  print $ Only (Sum 1) `mappend` Only (Sum 1)
1
Chandan