2015-10-04 8 views
7

Sto cercando di implementare MaybeT nello spirito della libreria mtl. Con questa soluzione non compilazione:Can GHC può derivare le istanze Functor e Applicative per un trasformatore monad?

{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-} 

import Control.Monad 
import Control.Monad.Trans 
import Control.Monad.State 

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } 

instance (Monad m) => Monad (MaybeT m) where 
    x >>= f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f) 
    return a = MaybeT $ return (Just a) 
    fail _ = MaybeT $ return Nothing 

instance MonadTrans MaybeT where 
    lift m = MaybeT (liftM Just m) 

instance (MonadIO m) => MonadIO (MaybeT m) where 
    liftIO m = lift (liftIO m) 

instance (MonadState s m) => MonadState s (MaybeT m) where 
    get = lift get 
    put = lift . put 

... 

ottengo l'errore:

Could not deduce (Applicative (MaybeT m)) arising from the superclasses of an instance declaration from the context (Monad m)

Se a implementare quanto segue, si compila:

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

instance (Monad m) => Functor (MaybeT m) where 
    fmap = liftM 

Può GHC fare questo per me?

+0

Correlato: http://stackoverflow.com/questions/18861231/why-is-there-no-xderiveapplicative-extension – dfeuer

risposta

5

No, GHC non può farlo al momento. Forse in futuro lo sarà.

La necessità di aggiungere istanze applicative è abbastanza nuova, introdotta con GHC 7.10 e la proposta "burn all bridge". Ciò risolveva alcune verruche della precedente gerarchia di classi, richiedendo infine che le monadi fossero sottoclassi di applicativi che sono sottoclassi di funtori. Sfortunatamente, questo rompe la retrocompatibilità e causa alcuni inconvenienti poiché non esiste un modo automatico per dedurre le istanze applicative.

Forse in futuro GHC permetterà qualcosa come

class Applicative m => Monad m where 
    return :: a -> m a 
    (>>=) :: m a -> (a -> m b) -> m b 
    default pure = return 
    default (<*>) = ap 

in modo che uno non ha bisogno di essere esplicito sulle istanze superclasse. O anche qualcosa basato su Template Haskell, in modo che uno scrittore di librerie possa spiegare a GHC come derivare automaticamente le istanze (che, in una certa misura, è fattibile in questo momento). Vedremo cosa proviene dagli sviluppatori di GHC.

+1

Al momento, c'è un 'return = pure' default nell'altro modo, quindi è possibile escluderlo . Ci sono anche piani per rendere 'return 'solo un sinonimo di' pure' in futuro. –

2

GHC potrebbe essere in grado di derivare l'istanza Functor, poiché è abbastanza buona a quelli. Ma l'unico modo in cui sa derivare un'istanza Applicative è derivato da newtype generalizzato, che non si applica qui.

Problemi correlati