这就是我对这个问题的解释,我很可能大错特错。
让我们看看的实现
sequence
(用于列表,不用于通用遍历)。
sequence = mapM id
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
mapM f as = foldr k (return []) as
where
k a r = do { x <- f a; xs <- r; return (x:xs) }
这没有捕获和丢弃错误的规定,所以让我们添加它。
sequenceNF :: MonadError e m => [m a] -> m [a]
sequenceNF = mapMNF id
mapMNF :: MonadError e m => (a -> m b) -> [a] -> m [b]
mapMNF f as = foldr k (return []) as
where k a r = do {
x <- f a; xs <- r; return (x:xs)
} `catchError` (\_ -> r)
现在我们可以:
sequenceNF [Just 42, Nothing, Just 13]
-- => Just [42, 13]
sequenceNF [print 42, ioError (userError "Oops"), print "Hi"]
-- => IO [(), ()]
-- will print 42 and "Hi" when executed
sequenceNF [
print "abc",
do { print 42; print "def" },
do { print "Hi"; ioError (userError "Oops"); print "Bye"; },
print "Ok" ]
-- => IO [(), (), ()]
-- will print: "abc" 42 "def" "Hi" "Ok"
-- note there are 4 elements in the input list
-- but only 3 elements in the output list
-- execution of the third element failed, so no value collected
-- although side effects of it are still executed