对于MaybeT的直觉

时间:2016-05-14 15:33:00

标签: haskell monad-transformers

我试图通过在MaybeT中运行一些示例来了解ghci

λ: import Control.Monad.Trans.Maybe
λ: let x = return $ 42 :: MaybeT (Either String) Int
λ: :t x
x :: MaybeT (Either String) Int

然后,我跑了它:

λ: runMaybeT x
Right (Just 42)

请给我价值y,以便

runMaybeT y === Left (Just "...")
runMaybeT y === Left Nothing
runMaybeT y === Right Nothing

2 个答案:

答案 0 :(得分:3)

你永远不会得到Left NothingLeft (Just ..),因为这里的monad是Either String …,所以在左边你总是会有String

以下是您可以获得的信息:

> let y = fail "Failed" :: MaybeT (Either String) Int
> runMaybeT y
Right Nothing
> let y = lift (Left "Failed") :: MaybeT (Either String) Int
> runMaybeT y
Left "Failed"

答案 1 :(得分:0)

这可能有助于深入了解使用MaybeT在幕后发生的事情......

在IO monad中我们有计算,例如

putStrLn "Hello, world!" :: IO ()
getContents :: IO String

等。所有这些计算都具有类型IO a,实际上类型变量a是不受限制的 - 它可以是任何类型。使用return,我们可以为任何类型IO a创建IO计算a

您可以将MaybeT IO视为返回Maybe值的IO计算。

例如,getContentsIO计算,但不是MaybeT IO计算。但是,有一种明显的方法可以将getContents转换为MaybeT IO计算 - 只需将其输出包装在Just构造函数中:

lift getContents   ===   fmap Just getContents

lift是将IO计算推广到MaybeT IO计算的方法。将此应用于return_IOreturn monad的IO函数),我们有:

return_(MaybeT IO) === lift return_IO === fmap Just return_IO

也就是说,return 3(在MaybeT IO monad中)与return (Just 3) monad中的IO相同。

runMaybeT和MaybeT是彼此的反转

现在看一下definition of MaybeT

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

这也描述了MaybeT m中的计算与返回Maybe值的m中的计算相同的想法。功能:

MaybeT    :: m (Maybe a) -> MaybeT m a
runMaybeT :: MaybeT m a  -> m (Maybe a)
除了添加或删除newtype包装器之外,

是彼此的反转并且不会做任何事情。在IO monad:

的情况下
MaybeT    :: IO (Maybe a) -> MaybeT IO a
runMaybeT :: MaybeT IO a  -> IO (Maybe a)

考虑到您问题中的示例,我们发现MaybeT (Either String)中的计算与任何类型Either String (Maybe a)的{​​{1}}类型的值基本相同。这导致了以下可能性:

    某些字符串的
  • a
  • Left
  • Right (Just ...)

这些都存在于Right Nothing中,如果我们将构造函数Either String (Maybe a)应用于每个MaybeT,我们会在MaybeT (Either String) a中获得相应的值。

特别要找到y s.t。

runMaybeT y == Right Nothing

只需使用:

          y = MaybeT (Right Nothing)

同样,runMaybeTMaybeT相互反转,因此您可以将MaybeT应用于双方,从而获得相同的结果。