MaybeT计算中的类型

时间:2015-02-13 09:01:06

标签: haskell monads monad-transformers maybe

在IO计算中工作我最终得到case mbValue of … s的阶梯,并且发现我应该使用Maybe monad来简化代码。由于它在IO计算范围内且我需要获得IO个值,因此我使用了MaybeT monad变换器,以便lift IO计算到{{} 1}}。

现在,我一直在考虑在Maybe计算中Maybe之后被values <- mbValue“剥离”的值,但事实证明这太简单了这里。

如下所示,当使用Maybe值作为Maybe a(此处将其传递给a)时,无法输入check:

read

如果我为import Control.Monad.Trans (lift) import Control.Monad.Trans.Maybe (runMaybeT) lol :: IO (Maybe Int) lol = return (Just 3) lal :: IO (Maybe String) lal = return (Just "8") foo :: IO (Maybe Bool) foo = do b <- runMaybeT $ do x <- lift lol y <- lift lal return (x < (read y)) return b ^-- Couldn't match type ‘Maybe String’ with ‘String’ main = foo >>= print 添加了一个输入的洞,我发现它需要一个return (x < (read y)),这是有道理的,但是当前的绑定还包括

Bool

即,|| y :: Data.Maybe.Maybe GHC.Base.String || (bound at /private/tmp/test.hs:14:5) || x :: Data.Maybe.Maybe GHC.Types.Int || (bound at /private/tmp/test.hs:13:5) y。这当然解释了错误,但我感到困惑。我的理解在哪里错了,我该如何解决这个错误?

2 个答案:

答案 0 :(得分:4)

简而言之:用lift构造函数替换MaybeT

请注意

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }

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

您在

中使用lift
x <- lift lol

属于

类型
lift :: IO (Maybe Int) -> MaybeT IO (Maybe Int)

这就是x再次成为Maybe Int的原因。 lift添加了一个新的MaybeT图层,该图层与您已有的Maybe图片无关。

但是

MaybeT :: m (Maybe a) -> MaybeT m a

而不是

x <- MaybeT lol

将用于

类型
MaybeT :: IO (Maybe a) -> MaybeT IO a

做正确的事。

答案 1 :(得分:4)

专门针对MaybeTlift :: Monad m => m a -> MaybeT m a。由于lol :: IO (Maybe Int)mIOaMaybe Int,因此为lift lol :: MaybeT IO (Maybe Int)

IO (Maybe a)只是MaybeT IO a newtype包装中包含的值,因此无需解除它;而是使用MaybeT构造函数,例如在MaybeT lol中。

但这不是人们倾向于使用monad变形金刚的方式。相反,只需使用MaybeT值并根据需要提升:

import Control.Monad
import Control.Monad.Trans (lift)
import Control.Monad.Trans.Maybe (runMaybeT, MaybeT)

lol :: MaybeT IO Int
lol = return 3

lal :: MaybeT IO String
lal = return "8"

foo :: IO (Maybe Bool)
foo = 
  runMaybeT $ do
    x <- lol
    y <- lal

    _ <- lift getLine -- lift (IO String) to MaybeT IO String
    _ <- return 100   -- lift any pure value    
    _ <- mzero        -- use the MonadPlus instance to get a lifted Nothing.

    return (x < (read y)) 

main = foo >>= print