如何将多个 monad 效果组合到同一个 do 块中?
How to combine multiple monad effects into the same do block?
我有一个函数调用 IO
类型的函数和 Either String a
类型的函数。
我想在 do 符号中合并效果,以便我可以在必要时解包 IO
,同时在遇到第一个 Left
时中止计算。
这是一个非常简单的例子,你能帮我解决一下吗? (使用 runEitherT 是可选的。但我认为如果你使用 plain either,你将无法使用 MonadError
和 MonadIO
功能)。
entryPoint :: IO (Either String Int)
entryPoint = runEitherT foo
-- p and p' should have type Int,
-- and errorf can force the computation to abort (as can throwError)
foo :: EitherT String IO Int
foo = do
p <- liftIO $ iof 1
p' <- return $ errorf p
if p' == 2
then throwError "No!"
else return 1
errorf :: b -> Either String b
errorf = undefined
iof :: a -> IO a
iof = undefined
部分
p' <- return $ errorf p
看起来不对。这里,return
在 EitherT String IO
中构建了一个 monadic 值。假设 errorf p = Left something
正在构建的值是
p' <- EitherT (return (Right (Left something)))
上面的 return
构建了一个 IO
动作。这不是我们想要的——那里有一个额外的 Right
。我们反而想要
p' <- EitherT (return (Left something))
也就是
p' <- EitherT $ return $ errorf p
我有一个函数调用 IO
类型的函数和 Either String a
类型的函数。
我想在 do 符号中合并效果,以便我可以在必要时解包 IO
,同时在遇到第一个 Left
时中止计算。
这是一个非常简单的例子,你能帮我解决一下吗? (使用 runEitherT 是可选的。但我认为如果你使用 plain either,你将无法使用 MonadError
和 MonadIO
功能)。
entryPoint :: IO (Either String Int)
entryPoint = runEitherT foo
-- p and p' should have type Int,
-- and errorf can force the computation to abort (as can throwError)
foo :: EitherT String IO Int
foo = do
p <- liftIO $ iof 1
p' <- return $ errorf p
if p' == 2
then throwError "No!"
else return 1
errorf :: b -> Either String b
errorf = undefined
iof :: a -> IO a
iof = undefined
部分
p' <- return $ errorf p
看起来不对。这里,return
在 EitherT String IO
中构建了一个 monadic 值。假设 errorf p = Left something
正在构建的值是
p' <- EitherT (return (Right (Left something)))
上面的 return
构建了一个 IO
动作。这不是我们想要的——那里有一个额外的 Right
。我们反而想要
p' <- EitherT (return (Left something))
也就是
p' <- EitherT $ return $ errorf p