我知道数据构造函数和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
答案 0 :(得分: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
(我必须在liftF'
)添加额外的Monad约束。
但你为什么要这样做?查看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实例以何种方式无法满足您的需求?