2015-10-04 10 views
7

Ich versuche MaybeT im Geiste der mtl Bibliothek zu implementieren. Mit dieser nicht-Kompilierung Lösung:Kann GHC Functor- und Applicative-Instanzen für einen Monad-Transformator ableiten?

{-# 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 

... 

bekomme ich den Fehler:

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

Wenn ich folgendes implementieren, es kompiliert:

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

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

Kann GHC tun dies für mich?

+0

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

Antwort

5

Nein, GHC kann dies derzeit nicht tun. Vielleicht wird es in Zukunft so sein.

Die Notwendigkeit, anwendungsspezifische Instanzen hinzuzufügen, ist eine ziemlich neue, die mit GHC 7.10 und dem Vorschlag "burn all bridges" eingeführt wurde. Dies behob einige Warzen der vorherigen Klassenhierarchie, indem schließlich gefordert wurde, dass Monaden Unterklassen von Anwendungen sind, die Unterklassen von Funktoren sind. Leider wird dadurch die Abwärtskompatibilität aufgehoben und es treten einige Unannehmlichkeiten auf, da es keine automatische Möglichkeit gibt, auf die anwendbaren Instanzen zu schließen.

Vielleicht in der Zukunft GHC wird so etwas wie

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

ermöglichen, so dass man braucht nicht über die übergeordnete Klasse Instanzen explizit zu sein. Oder sogar etwas, das auf Template Haskell basiert, so dass ein Bibliotheksautor GHC erklären kann, wie Instanzen automatisch abgeleitet werden (was bis zu einem gewissen Grad derzeit machbar ist). Wir werden sehen, was von den GHC-Entwicklern kommt.

+1

Gerade jetzt gibt es einen 'Rückkehr = reinen' Standard der andere Weg, also können Sie das weglassen . Es gibt auch Pläne, "Rückkehr" in Zukunft vielleicht nur noch ein Synonym für "rein" zu machen. –

2

GHC kann die Instanz Functor gut ableiten, da sie ziemlich gut ist. Aber die einzige Möglichkeit, eine Applicative Instanz abzuleiten, ist die verallgemeinerte Neuableitung, die hier nicht zur Anwendung kommt.