2015-04-24 12 views
7

Sto tentando di implementare un'istanza Monad. Come esempio più semplice, assumere i seguenti:Devo implementare Applicative e Functor per implementare una Monad

data Maybee a = Notheeng | Juust a 

instance Monad Maybee where 
    return x = Juust x 
    Notheeng >>= f = Notheeng 
    Juust x >>= f = f x 
    fail _ = Notheeng 

Questo dovrebbe essere l'implementazione standard di Forse per quanto ne so. Tuttavia, questo non viene compilato, perché il compilatore si lamenta:

Nessuna istanza per (applicativo Maybee)

e allo stesso modo vuole un'istanza Functor una volta che l'applicativo è dato.

Quindi: domanda semplice: devo sempre implementare Functor e Applicative prima di poter implementare una Monade?

+5

mi aspetto molto di domande su questo, sulla scia della versione di GHC 7.10. Dovremmo creare un tag * Functional-Applicative-Monad proposal *? – Jubobs

risposta

5

Con GHC 7,10 e al di sopra, è necessario implementare Functor e Applicative. Le definizioni di classe per Monad mandato le istanze della superclasse:

class Functor f => Applicative f where ... 
class Applicative m => Monad m where ... 

Notare che una volta si dispone di un'istanza Monad, i Functor e Applicative istanze possono essere definiti genericamente senza sforzo aggiuntivo:

import Control.Monad 

-- suppose we defined a Monad instance: 
instance Monad m where ... 

instance Functor m where 
    fmap = liftM 

instance Applicative m where 
    pure = return 
    (<*>) = ap 
+2

In realtà non è vero: in 7.8 e precedenti, 'Monad' non aveva alcun vincolo di superclasse. –

+0

Duh, è un grosso errore da parte mia. –

+0

@ 4castle sì; modificato. –

8

È obbligatorio definire istanze per Functor e Applicative (il secondo è un nuovo requisito nelle versioni più recenti di Haskell), ma in realtà non è un grosso problema perché se non si desidera scrivere a mano le proprie istanze si può semplicemente utilizzare questi:

import Control.Applicative (Applicative(..)) 
import Control.Monad  (liftM, ap) 

-- Monad m 

instance Functor m where 
    fmap = liftM 

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