在我目前的项目中,我遇到了将各种monad变成变压器对应物的需要,例如。
stateT :: Monad m => State s a -> StateT s m a
stateT stf = StateT $ return . runState stf
为我需要的monad编写这些实用程序函数是微不足道的,但我想知道是否已经存在一个包含标准monad的这个功能的库,也许是一个抽象这种转换的类型类。像
这样的东西class (Monad f, MonadTrans t) => LiftTrans f t | f -> t where
liftT :: Monad m => f a -> t m a
(“升力”可能是在这里使用的错误术语,但我不知道还有什么可以称之为。)
答案 0 :(得分:17)
从mmorph包中查看功能hoist
。
它的签名是
hoist :: Monad m => (forall a. m a -> n a) -> t m b -> t n b
这意味着它可以改变变压器下面的基础monad。
现在,在trasformers
包中,许多“基本”monad被实现为应用于Identity
monad的变换器,如下所示:
type State s = StateT s Identity
因此,我们可以定义以下函数(从mmorph
文档的Generalizing base monads部分开始):
import Data.Functor.Identity
generalize :: (Monad m) => Identity a -> m a
generalize m = return (runIdentity m)
并将其与升降机结合使用:
hoist generalize :: (Monad m, MFunctor t) => t Identity b -> t m b
此方法不适用于未定义为应用于Identity
的变换器的简单monad,如Maybe
和Either
monad。您可能会遇到hoistMaybe和hoistEither。
答案 1 :(得分:0)
你试图走错路。如果某个东西是变换器,那么它的简单版本就是应用于Identity monad的变换器。 (它们并不总是像那样直接实现,但应该等效于模数底部。)但是,并非所有的monad都是变换器(它们需要普遍左边或普遍右边伴随才能变换。[需要引证])
升降机和朋友也非常有帮助,但我认为最好颠倒你的过程。