如何在haskell中将功能提升到变形monad?

Zna*_*atz 2 monads haskell monad-transformers

我知道数据构造函数和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
Run Code Online (Sandbox Code Playgroud)

但是我怎样才能将这个liftF推广到

liftF :: (MonadTrans t, Monad m) => (a -> b) -> t m a -> t m b
Run Code Online (Sandbox Code Playgroud)

Mat*_*ick 5

正如@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
Run Code Online (Sandbox Code Playgroud)

(我不得不添加额外的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)
Run Code Online (Sandbox Code Playgroud)

实际上,liftM和Functor一样fmap:

instance (Functor m) => Functor (MaybeT m) where
    fmap f = mapMaybeT (fmap (fmap f))
Run Code Online (Sandbox Code Playgroud)

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

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