2014-09-05 15 views
6

Haskell kann die Instanz für MonadState s in T1 unten aber nicht in T2 ableiten, das jedoch ein sehr ähnlicher Typ ist. Wie soll ich den Code für T2 ändern, damit die Instanz für automatisch abgeleitet werden kann?Verallgemeinerter Newtyp Ableiten

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

import Control.Monad.Reader 
import Control.Monad.State 

newtype T1 r s a = 
    T1 { runT1 :: ReaderT r (State s) a } 
    deriving (Monad, MonadReader r, MonadState s) 

newtype T2 r s a = 
    T2 { runT2 :: StateT r (State s) a } 
    deriving (Monad, MonadState r, MonadState s) 

Antwort

7

Sie können keinen Typ haben zwei Instanzen für MonadState. Dies liegt daran, MonadState als

class Monad m => MonadState s m | m -> s where 
    get :: m s 
    set :: s -> m() 
    state :: (s -> (a, s)) -> m a 

Der wichtigste Teil der | m -> s ist definiert ist. Dies erfordert die Erweiterung FunctionalDependencies und besagt, dass für jede m automatisch die zugehörige s bekannt ist. Dies bedeutet, dass für jede gegebene m, kann nur eine Wahl für s, die gültig ist. Sie können also nicht für MonadState r m und arbeiten, es sei denn, r ~ s. Wenn r ~ s, wie würde dann der Compiler wissen, für welche zugrundeliegende Monade er gelten soll? In diesem Fall werden Sie feststellen, dass es viel einfacher ist, den Code zu verstehen und mit dem Code zu arbeiten, wenn Sie get und put Funktionen mit Suffixen wie getInner, setInner und getOuter, setOuter erstellen.

Verwandte Themen