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

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 1/2 天的构造函数折纸之后我能想到的最好的就是你在上面看到的那个:unwrapped 应该是一个 (Maybe 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)'

我错过了什么?

最佳答案

listen 具有类型签名

  m a -> m (a, w)

IE。
 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 的实现。)

关于typeclass - 如何将 Maybe-Transformer MaybeT 变成 MonadWriter 的实例?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2751621/

10-13 03:09