Haskell 如何将多个单子效果组合到同一do块中?

Haskell 如何将多个单子效果组合到同一do块中?,haskell,monads,monad-transformers,Haskell,Monads,Monad Transformers,我有一个函数,它调用类型为IO的函数和类型为的函数,要么调用字符串a 我想将do符号中的效果组合起来,以便在必要时解包IO,同时在我遇到的第一个左侧处中止计算 这里有一个非常简单的例子,你能帮我修复它吗?(使用runEitherT是可选的。但我认为如果使用plain,您将无法使用MonadError和MonadIO功能) entryPoint::IO(字符串或Int) 入口点=runEitherT foo --p和p'的类型应为Int, --而errorf会迫使计算中止(与throwError一

我有一个函数,它调用类型为
IO
的函数和类型为
的函数,要么调用字符串a

我想将do符号中的效果组合起来,以便在必要时解包
IO
,同时在我遇到的第一个
左侧
处中止计算

这里有一个非常简单的例子,你能帮我修复它吗?(使用runEitherT是可选的。但我认为如果使用plain,您将无法使用
MonadError
MonadIO
功能)

entryPoint::IO(字符串或Int)
入口点=runEitherT foo
--p和p'的类型应为Int,
--而errorf会迫使计算中止(与throwError一样)
foo::EitherT字符串IO Int
foo=do
p或字符串b
errorf=未定义
iof::a->IO a
iof=未定义
零件

p' <- return $ errorf p
其中,上面的
返回
构建了一个
IO
操作。这不是我们想要的——这里有一个额外的
右边的
。相反,我们想要

p' <- EitherT (return (Left something))

p'
p'我不明白你为什么要使用
EitherT
然后抛出
undefined
about。这看起来很奇怪。你到底想完成什么?名称
entryPoint
foo
不是那么具有描述性。因为实现并不重要,只要您知道一个方法不执行IO,另一个方法使用其中一个来报告错误。我非常确定字符串IO Int是我需要的行为的正确类型,所以我只需要代码typecheck@chi它编译好了,谢谢。所以基本上
return$errorf p'
已经有了抽象意义上的正确类型,但我不得不将其进一步打包到
EitherT
中,以满足类型检查器的要求。原始的
return$x
位于
EitherT s IO
中,表示成功,建模为
EitherT(return(Right x))
,后者
return
生成
IO
。因此,原始代码构建了
EtiherT(return(Right(Left…))
,因为
x=Left..
这是错误的。相反,我们使用
EitherT$return$errorf p
来生成
IO
(而不是
EitherT…
),因此我们得到
EitherT(return(Left…)
)。这很奇怪,因为我们似乎在进一步打包它,而我们没有:添加
EitherT
使Haskell选择一个不同的
返回
(在
IO
中,而不是
EitherT
)!为什么要将Control.Monad.Error.Class中的throwError更改为left?它是用throwError编译的,我觉得这个名字更能体现语义。@BruceBerry我对throwError的看法是错误的,
IO
——我以为有人在引发异常,但事实并非如此。
p' <- EitherT (return (Right (Left something)))
p' <- EitherT (return (Left something))
p' <- EitherT $ return $ errorf p