2010-05-01 21 views
4

我想基於真實世界哈斯克爾的例子中,章單子變形金剛建設MaybeT變壓器單子,:如何將一個Maybe-Transformer MaybeT變成一個MonadWriter的實例?

data MaybeT m a = MaybeT { runMT :: m (Maybe a) } 

instance (Monad m) => Monad (MaybeT m) where 
    m >>= f = MaybeT $ do a <- runMT m 
         case a of 
          Just x -> runMT (f x) 
          Nothing -> return Nothing 
    return a = MaybeT $ return (Just a) 

instance MonadTrans MaybeT where 
    lift m = MaybeT $ do 
        a <- m 
        return (Just a) 

這工作得很好,但現在我想打MaybeT的MonadWriter實例:

instance (MonadWriter w m) => MonadWriter w (MaybeT m) where 
tell = lift . tell 
listen m = MaybeT $ do unwrapped <- listen (runMT m) 
         return (Just unwrapped) 

告訴是好的,但我不能讓功能權限。在構造函數摺紙的1/2天之後,我能想到的最好的是你在上面看到的那個:unwrapped應該是(也許a,w)的一個元組,並且我想要包含在Maybe鍵入並把整個東西放在一個空的MonadWriter中。

但是編譯器抱怨:

Occurs check: cannot construct the infinite type: a = Maybe a 
    When generalising the type(s) for `listen' 
    In the instance declaration for `MonadWriter w (MaybeT m)' 

我缺少什麼?

回答

6

listen具有類型簽名

m a -> m (a, w) 

MaybeT m a -> MaybeT m (a, w) 

但是​​具有類型簽名

MaybeT m a -> MaybeT m (Maybe a, w) 

所以無限型引發錯誤。你需要轉換的是unwrapped :: (Maybe a, w)Maybe (a, w)着手:

listen m = MaybeT $ do (val, wr) <- listen (runMT m) 
        case val of 
         Nothing -> return Nothing 
         Just x -> return (Just (x, wr)) 

(順便說一句,有MaybeT的http://www.haskell.org/haskellwiki/New_monads/MaybeT的實現。)

+0

@KennyTM:非常感謝!非常快速,非常精確! – martingw 2010-05-01 22:12:29

相關問題