2016-05-24 55 views
2

例如,我有這個功能如何在ExceptT和List中使用遍歷,只有在所有項都是Left時才返回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 

返回

Left "x == 0" 

但我想Right [1,2] 和它應該返回Left只有當所有列表項目爲零

+2

你什麼樣的回報爲空表? –

+0

我的情況並不重要,所以它可能是'正確'或'左' – ais

+0

你可能會也可能不會發現['ExceptRT'](https://hackage.haskell.org/package/errors-2.1.2 /docs/Data-EitherR.html)有用。 – dfeuer

回答

2

這是一個關於traverse的問題?或者您僅是想收集foo的結果,此投票不引起異常?

後者的直接方式是在「try-catch」塊中運行foo的每個調用,該塊返回Maybe Int,然後返回列表。

例子:

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