2013-10-17 41 views
0

我要一个一元值转换成其他的单子类的一元价值。哈斯克尔从IO皈依米

可以说我有一个实例声明:

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

ClassM:是定义一个自己的单子类
TypeT:是自己定义的类型/有单子实例数据执行
ABC:是类型IO一个

如何转换ABC :: IO的一元值的
到的classM米一个monadic值=>毫安
又名M1一个 - >米2(其中,m1是不平方米) (例如:IO 5 - >仅有5)

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

谢谢你的时间和帮助。

+1

对'm a'到'IO a',看看'MonadIO'中的'liftIO'。更一般地说,从'MonadTrans'提升''。否则,也许你会对'mmorph'包感兴趣。 – thoferon

+1

你可能意识到了这一点,但只是说:'\ X - >回x'简直是'return',并通过法律的单子'V >> = return'必须是'v'再次,始终。所以目前你只有'funcX = abc'。 – leftaroundabout

+1

这是不可能通过设计。你不能从一个值解开IO。它永远像钻石一样。或许,如果你告诉我们你想解决什么问题,我们就可以帮你。 –

回答

-1

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

你问Comonads - >Monad转型:Comonad package

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

在任何情况下,你不能从IO

comonad

你可以使用使用unsafePerormIO

+2

在'unsafePerformIO':你可能* *,但在大多数情况下,你不应该。 – duplode

5

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 

之一,而且一般是不可能的,虽然one type of very special monads具有这种性质。

你可以做的另一件事是在底部使用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 

例如,最简单的很是MonadTransIdT

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 

这只是彼此的反转,在这种情况下。一般来说,行为可能更复杂。