1

我想将一个单子值转换为另一个单子类的单子值。

假设我有一个实例声明:

    instance ClassM TypeT where
        funcX = abc >>= \x -> return (x)

ClassM:是一个自己的 monad 定义的类
TypeT:是一个自己定义的类型/数据,具有一个 monad 实例实现
abc:是 IO a 类型

我如何将 abc::IO a
的一元值转换为 classM m => ma
aka m1 a -> m2 a 的一元值(其中 m1 不是 m2)(例如:IO 5 -> Just 5)

我对 funcX 的实现显然是不正确的。如果可能,正确的实现应该是什么?

感谢您的时间和帮助。

4

2 回答 2

7

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

在这种情况下,它们只是彼此的倒数。一般来说,行为可能要复杂得多。

于 2013-10-17T13:21:57.823 回答
-1

Monad“类”它不是来自对象的“类”。

您在询问Comonads->Monad转换:Comonad 包

convert :: (Comonad w, Monad m) => w a -> m a
convert = return . extract

在任何情况下,您都不能从 IO 获得 comonad

你可以使用一些hackeryunsafePerormIO

于 2013-10-17T12:10:01.633 回答