3

我知道数据构造函数和 run*** 函数,

我可以将任何功能提升到特定的 MonadTrans 实例。

像这样,

import Control.Monad.Trans
import Control.Monad.Trans.Maybe
import Control.Monad

liftF :: (Monad m) => (a -> b) -> MaybeT m a -> MaybeT m b
liftF f x = MaybeT $ do
       inner <- runMaybeT x
       return $ liftM f inner

但是我怎样才能将这个 liftF 概括为

liftF :: (MonadTrans t, Monad m) => (a -> b) -> t m a -> t m b
4

1 回答 1

6

正如@thoferon 提到的,您可以使用liftM

import Control.Monad.Trans
import Control.Monad.Trans.Maybe
import Control.Monad (liftM)

liftF :: (Monad m) => (a -> b) -> MaybeT m a -> MaybeT m b
liftF f m = liftM f m

liftF' :: (MonadTrans t, Monad m, Monad (t m)) => (a -> b) -> t m a -> t m b
liftF' f m = liftM f m

(我不得不添加一个额外的 Monad 约束liftF')。

但你为什么要这样做?查看源代码MaybeT——已经有一个 Monad 实例:

instance (Monad m) => Monad (MaybeT m) where
    fail _ = MaybeT (return Nothing)
    return = lift . return
    x >>= f = MaybeT $ do
        v <- runMaybeT x
        case v of
            Nothing -> return Nothing
            Just y  -> runMaybeT (f y)

实际上,liftM与 Functor 的一样fmap

instance (Functor m) => Functor (MaybeT m) where
    fmap f = mapMaybeT (fmap (fmap f))

您可以找到所有变压器的类似实例。

这是你要问的吗?您能否提供一些更具体的示例来说明您正在尝试做什么以及为什么,以及现有的 Functor 和 Monad 实例以何种方式无法满足您的需求?

于 2013-05-17T12:42:09.823 回答