如何在Haskell中解决这个monadT关系?

时间:2015-04-30 04:46:01

标签: haskell monad-transformers

我在学习haskell monad变形金刚时遇到了这个问题。 假设我有一个instance Monad m => Monad (CustomT m)类型。

如果有f :: CustomT IO Int功能,那就是g :: IO (Maybe Int)

如何访问Intg的{​​{1}}?

我试过像

这样的东西
f

这不起作用,因为f = do mVal <- g 位于f monad下,而CustomT IO位于g monad下。

然后我尝试了

MaybeT IO

这似乎有效但f = do mVal <- return g mVal类型,我最终会像IO (Maybe Int)

那样嵌套IO

有没有办法在CustomT IO (IO something)中获取IntMaybe Int

涉及哪些知识? 提前谢谢。

2 个答案:

答案 0 :(得分:3)

在一般情况下,Jeremy的答案就是你想要的。但是,让我们看看我们是否可以在这里处理您的具体案例。我们有f :: CustomT IO Intg :: IO (Maybe Int),因为instance Monad m => Monad (CustomT m)instance MonadTrans CustomT有一些实例。

你想要的是在Int的上下文中g内的CustomT IO。由于我们在CustomT内部,我们基本上可以轻松剥离该层。就像杰里米说的那样,用lift来摆脱它。

lift :: (MonadTrans t, Monad m) => m a -> t m a

现在我们有了CustomT IO (Maybe Int)。就像我说的那样,我们在do - 块内,所以使用Haskell的bind(<-)语法暂时删除monad层。因此,我们正在处理Maybe Int。要从Maybe Int转到Int,通常的方法是使用maybe

maybe :: b -> (a -> b) -> Maybe a -> b

这提供了默认值,以防Maybe Int实际为Nothing。因此,例如,maybe 0 id是一个函数,它接受Maybe Int并产生内部Int0,如果值为Nothing。所以,最后,我们有:

f = do
  mVal <- maybe 0 id $ lift g
  -- Other code

答案 1 :(得分:2)

Control.Monad.Trans中你有monad变换器的这个定义:

class MonadTrans (t :: (* -> *) -> * -> *) where
  lift :: Monad m => m a -> t m a

这意味着如果CustomT已正确定义,您可以执行此操作:

f = do
  mVal <- lift g