我想将monadic值转换为另一个Monad类的monadic值.
让我们说我有一个实例声明:
instance ClassM TypeT where
funcX = abc >>= \x -> return (x)
Run Code Online (Sandbox Code Playgroud)
ClassM:是一个自己的monad定义类
TypeT:是一个自己定义的类型/数据,带有monad实现实现
abc:类型为IO a
我如何将abc :: IO a
的monadic值转换为classM的monadic值m => ma
又名m1 a - > m2 a(其中m1不是m2)(例如:IO 5 - >只是5)
我对funcX的实现显然不正确.如果有可能,那么正确的实施应该是什么?
感谢您的时间和帮助.
Monad这个类代表所有monad的东西---它不是一个名词而是一个形容词.如果你想将一个特定的monad转换为一个在所有monad中都是通用的值,那么这个类型看起来就像其中之一
Monad m => IO a -> m a
Monad m => Maybe a -> m a
Monad m => [a] -> m a
Monad m => Either e a -> m a
Run Code Online (Sandbox Code Playgroud)
虽然有一种非常特殊的monad具有这种特性,但它通常是不可能的.
您可能要做的另一件事是在底部使用Monad变压器IO.这意味着您将另一个monad"叠加在"之上IO.这使您可以进行常规操作
lift :: MonadTrans t => m a -> t m a -- notice that t takes two parameters
lift :: IO a -> MyTransformer IO a -- specializing the generic function
Run Code Online (Sandbox Code Playgroud)
并且,MyTransformer具体操作取决于具体操作
runMyTransformer :: MyTransformer m a -> m a
runMyTransformer :: MyTransformer IO a -> IO a -- specialized
Run Code Online (Sandbox Code Playgroud)
例如,最简单的MonadTrans是IdT.
newtype IdT m a = IdT { runIdT :: m a } deriving Functor
instance Monad m => Monad (IdT m) where
return a = IdT (return a)
IdT ma >>= f = IdT (ma >>= runIdT . f)
instance MonadTrans IdT where
lift ma = IdT ma
Run Code Online (Sandbox Code Playgroud)
给我们操作
lift :: IO a -> IdT IO a
runIdT :: IdT IO a -> IO a
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它们只是彼此相反.通常,行为可能要复杂得多.