如何将遍历与 ExceptT 和 List 一起使用,以便它 returns 仅当所有项目都离开时才离开?

How to use traverse with ExceptT and List so it returns Left only if all items are Left?

比如我有这个功能

foo :: Int -> ExceptT String (State Int) Int
foo x = if x == 0 then throwError "x == 0" else return x

如果我使用 traverse

evalState (runExceptT $ traverse foo [0,1,2]) 0

它returns

Left "x == 0"

但是我想要Right [1,2] 它应该 return Left 只有当所有列表项都为零时

这是关于 traverse 的问题,还是您只想收集 foo 的结果而不抛出异常?

后者的直接方法是 运行 在 "try-catch" 块中对 foo 的每次调用,其中 returns 一个 Maybe Int,然后 catMaybes 名单。

示例:

import Data.Maybe
import Control.Monad
import Control.Monad.Except
import Control.Monad.State

foo :: Int -> ExceptT String (State Int) Int
foo x = if x == 0 then throwError "x == 0" else return x

orNothing p = catchError (fmap return p) (\e -> return Nothing)

collectFoos xs = do ys <- fmap catMaybes $ mapM (orNothing . foo) xs
                    case ys of
                      [] -> throwError "no successful call to foo"
                      _  -> return ys

doit xs = runState (runExceptT (collectFoos xs)) 100