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
这通常是不可能的,尽管一种非常特殊的单子具有此属性。
您可能会做的另一件事是使用底部的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
并且,取决于MyTransformer
具体的操作
runMyTransformer :: MyTransformer m a -> m a
runMyTransformer :: MyTransformer IO a -> IO a -- specialized
例如,最简单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
给我们操作
lift :: IO a -> IdT IO a
runIdT :: IdT IO a -> IO a
在这种情况下,它们只是彼此的倒数。一般来说,行为可能要复杂得多。