假设我有以下功能:
checkA :: a -> Either err b
checkA = undefined
checkB :: b -> ST s (Either err c)
checkB = undefined
check :: a -> ST s (Either err c)
check a = either (return . Left) checkB (checkA a)
有没有办法写check
这样就不需要使用 return . Left
?通常我会做类似 >>=
的事情,但在本例中返回 checkB
被包裹在另一个状态单子(monad)中,所以它不起作用。另一个约束是checkB
应该仅在 checkA a
时运行计算结果为Right
,并且应该会失败并出现 Left
上的错误
概括来说,是否有使用嵌套 monad 的标准方法?
最佳答案
这是使用 ExceptT
执行此操作的一种方法:
checkA :: a -> Either err b
checkA = undefined
checkB :: b -> ExceptT err (ST s) c
checkB = undefined
check :: a -> ExceptT err (ST s) c
check a = except (checkA a) >>= checkB
-- or
check = except . checkA >=> checkB
except
将 Either err b
转换为 Monad m => exceptT err m b
,然后你就可以在 中执行其他操作exceptT err (ST s)
monad。
作为一般规则,ExceptT
是处理单子(monad)操作的好方法,当您通常想要在失败时放弃时,这些操作可能会失败。主要的异常是底层 monad 为 IO 时,在这种情况下,更常见的是使用 Control.Exception 中的内置异常功能。
当然,如果您只需要一个单子(monad)绑定(bind),ExceptT
似乎有点大材小用,但一旦您需要更多,它肯定是有意义的。
关于haskell - 处理 Either 和 ST monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55264051/