如何在haskell中将函数提升到变换后的monad?
我知道使用数据构造函数和run***函数 我可以将任何函数提升到特定的MonadTrans实例 像这样,如何在haskell中将函数提升到变换后的monad?,haskell,monads,monad-transformers,Haskell,Monads,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 <- r
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
正如@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约束)
但你为什么要这么做?查看的源代码--已经有一个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)
您可以找到所有变压器的类似实例
这就是你要问的吗?你能提供一些更具体的例子来说明你想做什么,为什么,以及现有的Functor和Monad实例以什么方式不能满足你的需要吗?为什么不使用
liftM
TM
本身就是单子。@thoferon,是的,但是liftM
也不是广义的。因为在使用liftM
之前,我必须编写实例Monad(SomeMonadTrans m),其中…
,所以我仍然必须知道SomeMonadTrans。我的英语很抱歉。我的意思是,在Monad
的情况下,只要SomeType
是Monad
的一个实例,我们就不需要重新定义liftM
。对于通用MonadTrans t,我必须在使用liftM
之前定义TM
aMonad
。有没有办法跳过这一步?或者说,对于每个通用的MonadTrans
实例是否都有一个通用的liftF
?@Znatz但是在标准库中,作为MonadTrans
实例的每个数据类型也是Monad
的实例,因此liftM
将与所有转换器一起工作。谢谢。我现在明白了。我必须将MonadTrans t=>tm
的泛型实例定义为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)
instance (Functor m) => Functor (MaybeT m) where
fmap f = mapMaybeT (fmap (fmap f))