4

Real World Haskell、Chapter Monad Transformersの例に基づいて、MaybeT-TransformerMonadを構築しようとしています。

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日半後に私が思いつくことができる最高のものはあなたが上で見るものです:アンラップは(多分a、w)のタプルであるはずであり、多分タイプでラップしたいです全部を空の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)'

私は何が欠けていますか?

4

1 に答える 1

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

(ところで、MaybeTの実装はhttp://www.haskell.org/haskellwiki/New_monads/MaybeTにあります。)

于 2010-05-01T21:59:20.970 に答える