2013-07-15 18 views
5

Docs dla monad-control podać przykład, w jaki sposób utworzyć instancję MonadTransControl korzystając defaultLiftWith i defaultRestoreT. Przykładem jest następujący newtype:instancja MonadTransControl dla niestandardowego monady

newtype CounterT m a = CounterT {unCounterT :: StateT Int m a} 

Przykład ten może być dostosowany do pracy w dowolnym newtype że określona jest tylko jedna „podstawową” transformatora monadę (takie jak te z transformers lub mtl). Ale co z przypadkiem, w którym stos zawiera dwa "elementarne" transformatory? Na przykład, w jaki sposób możemy zdefiniować instancję MonadTransControl czegoś takiego:

newtype T m a = T {unT :: MaybeT (StateT Int m) a} 

Moim problemem jest to, że nie wiem jak ustawić następującą linię

newtype StT CounterT a = StCounter {unStCounter :: StT (StateT Int) a} 

z CounterT aby go pracować dla mojego transformatora T. W szczególności nie wiem, co umieścić w ostatnim nawiasie. Oczekuje czegoś, co ma charakter (* -> *) -> * -> *, ale nie mogę stworzyć czegoś takiego.

Wszelkie pomysły?

Odpowiedz

3

I nie były w stanie ponownie wykorzystać defaultLiftWith i defaultRestoreT, ale patrząc na ich kodu źródłowego i szczypanie go lekko, przyjechałem na następujące:

newtype CounterT m a = CounterT {unCounterT :: MaybeT (StateT Int m) a} deriving (Monad) 

instance MonadTrans CounterT where 
    lift = CounterT . lift . lift 

instance MonadTransControl CounterT where 
    newtype StT CounterT a = StCounter {unStCounter :: StT (StateT Int) (StT MaybeT a)} 
    liftWith = \f -> 
     CounterT $ liftWith $ \run -> 
        liftWith $ \run' -> 
        f $ liftM StCounter . run' . run . unCounterT    
    restoreT = CounterT . restoreT . restoreT . liftM unStCounter 
+0

Dzięki, że działa. Najwyraźniej nie można tego zrobić za pomocą 'defaultLiftWith' /' defaultRestoreT'. Przypuszczalnie są one tylko dla prostych przypadków. Myślę, że nie zamierzam w końcu używać 'MonadBaseControl'. Wydaje się to zbyt skomplikowane i obawiam się, że w przyszłości interfejs API ulegnie zmianie, co utrudni utrzymanie mojego kodu. – safsaf32