如何将Maybe-Transformer MaybeT变成MonadWriter的实例?

时间:2010-05-01 21:33:13

标签: typeclass monad-transformers haskell

我正在尝试构建一个MaybeT-Transformer Monad,基于 Real World Haskell 中的示例,章节 Monad Transformers

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)

tell 没问题,但我无法正确使用 listen 功能。在构造函数折纸的1 1/2天之后,我能想出的最好的是你在上面看到的那个: unwrapped 应该是(也许a,w)的元组,并且我想要在Maybe-Type中包装并将整个事物放在一个空的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)'

我错过了什么?

1 个答案:

答案 0 :(得分:6)

listen有类型签名

  m a -> m (a, w)

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

MaybeT $ listen (runMT m) >>= return . Just有类型签名

 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))

(顺便说一句,在http://www.haskell.org/haskellwiki/New_monads/MaybeT中有一个MaybeT的实现。)