web-dev-qa-db-fra.com

Définir une nouvelle monade dans haskell ne soulève aucune instance pour Applicative

J'essaie de définir une nouvelle monade et j'obtiens une étrange erreur

newmonad.hs

 newtype Wrapped a = Wrap {unwrap :: a} 
 instance Monad Wrapped où 
 (>> =) (Wrap x) f = fx 
 return x = Wrap x 
 
 Main = do 
 PutStrLn "yay" 
 $ ghc --version 
 Le Glorious Glasgow Haskell Compilation System, version 7.10.1 
 
 $ ghc newmonad.hs 
 [1 sur 1 ] Compilation principale (newmonad.hs, newmonad.o) 
 
 Newmonad.hs: 2: 10: 
 Aucune instance pour (Applicative Wrapped) 
 Résultant de la superclasses d'une déclaration d'instance 
 Dans la déclaration d'instance pour "Monad Wrapped" 

Pourquoi dois-je définir une instance de Applicative?

53
fakedrake

Il s'agit de la proposition de monade applicative (AMP). Maintenant, chaque fois que vous déclarez quelque chose comme Monad, vous devez également le déclarer comme Applicative (et donc Functor). Mathématiquement parlant, chaque monade est un foncteur applicatif, donc cela a du sens.

Vous pouvez effectuer les opérations suivantes pour supprimer l'erreur:

instance Functor Wrap where
  fmap f (Wrap x) = Wrap (f x)

instance Applicative Wrap where
  pure = Wrap
  Wrap f <*> Wrap x = Wrap (f x)

https://wiki.haskell.org/Functor-Applicative-Monad_Proposal

Edit: Peut-être devrais-je souligner plus clairement que c'est une chose récente? Le code que vous avez publié fonctionnait auparavant, mais avec les versions récentes de GHC, vous obtiendrez une erreur. C'est un changement de rupture.

Edit: Les déclarations suivantes devraient fonctionner pour any monad:

import Control.Applicative -- Otherwise you can't do the Applicative instance.
import Control.Monad (liftM, ap)

instance Functor ??? where
  fmap = liftM

instance Applicative ??? where
  pure  = return
  (<*>) = ap

Selon la monade en question, il peut y avoir des implémentations plus efficaces possibles, mais c'est un point de départ simple.

81
MathematicalOrchid

La réponse la plus normalisée et discrète est: -

comme Monad dépend de Applicative

classe Applicative m => Monade m où ...

et Applicatif dépend de Functor

classe Functor f => Applicative f où ...

nous avons besoin des définitions d'instance

> instance Functor Wrapped where
>     fmap = liftM

et

> instance Applicative Wrapped where
>     pure = return
>     (<*>) = ap
1
AaronNGray