Как я могу превратить Maybe-Transformer MaybeT в экземпляр MonadWriter? - PullRequest
4 голосов
/ 02 мая 2010

Я пытаюсь построить монаду MaybeT-Transformer, основываясь на примере из Real World Haskell , глава Трансформаторы монад :

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)

скажите в порядке, но я не могу правильно настроить функцию listen . Лучшее, что я мог придумать после 1 1/2 дня конструктора оригами, это то, что вы видите выше: unwrapped должен быть кортежем (возможно 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)'

Что мне не хватает?

1 Ответ

6 голосов
/ 02 мая 2010

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

...