2016-04-10 5 views
1

In diesem Dokument rufen wir liftIO in eval6 auf, um E/A-Aktionen auszuführen. Warum müssen wir in diesem Fall heben? Weil es keine IO-Klasse für gibt, die wir einen Typ als instanziieren können. Bei E/A-Aktionen müssen wir daher aufrufen, um die Befehle nach innen zu senden. Für Eval6 würden wir Aufzug viermal zusammensetzen müssen, um etwas zu drucken. Dies ist nur unbequem, so dass die Leute eine neue Klasse erstellen MonadIO, so dass wir nur brauchen liftIO einmal zu nennen, ohne zu zählen, wie viele mal Lift zu komponieren zu halten mit:liftIO anstelle der Komposition lift

class (Monad m) => MonadIO m where 
liftIO :: IO a -> m a 
instance MonadIO IO where 
liftIO = id 
instance (Error e, MonadIO m) => MonadIO (ErrorT e m) where 
liftIO = lift . liftIO 
instance (MonadIO m) => MonadIO (ReaderT r m) where 
liftIO = lift . liftIO 

Das Zitat kommt von http://www.cs.virginia.edu/~wh5a/personal/Transformers.pdf

Und wieder kann ich nicht verstehen, warum ohne liftIO wir liftIO vier mal anrufen müssten. Ich kann es nicht deshalb sehen Sie bitte klar machen;)

Antwort

1
class MonadTrans t where 
    lift :: Monad m => m a -> t m a 

Wenn Sie

foo :: Monad m => m a -> ExceptT e (StateT s (ReaderT r m)) a 

wollen, dann müssen Sie lift einmal für jeden der Typkonstruktoren anzuwenden. Zuerst bekommen wir

lift :: Monad m 
    => m a -> ReaderT r m a 

dann

lift . lift :: Monad m 
    => m a -> StateT s (ReaderT r m) a 

dann

foo = lift . lift . lift :: Monad m 
    => m a -> ExceptT e (StateT s (ReaderT r m)) a