2017-08-29 36 views
2

(這個問題類似於this question但這個問題只得到的評價推薦的errors包,我想的更多細節。)在`ExceptT`計算不同的錯誤類型處理

我工作的一個程序使用兩種不同的軟件包,它們都返回IO (Either e a)Either e a。但是這些庫之間的e不一樣。

我想知道如何構造使用這兩個庫的函數。我應該使用errors的提示使我hushnote,但這並不感到很正確:

data MyError = Error1 | Error2 | Error3 

f :: IO (Either MyErrorType Text) 
f = do 
    now <- someIoAction 

    runExceptT $ do 
    x <- note Error1 $ hush LibraryA.f 
    y <- ExceptT $ note Error2 . hush <$> LibraryB.IO.f 
    z <- ExceptT $ note Error3 . hush <$> LibraryB.IO.g 
    pure (x, y, z) 

應該怎樣一個結構類似的代碼?我應該匹配結果並轉換錯誤類型嗎?我應該瞭解的errors包中是否還有其他內容?我將非常感謝關於如何構造類似上面的代碼的一些(有點)具體問題的答案以及處理Haskell中的非一致錯誤的一般指針。

+1

最簡單的解決方法是在'Either(e1 e2)a'或'ExceptT(e1 e2)m''中使用例如'withExceptT'來將每個較小的計算嵌入到較大的計算中。當你有很多錯誤類型需要處理時,這種方法開始變得笨重(儘管看起來你現在只有兩種錯誤類型)。 –

+0

這真的取決於上下文。如果你想寫一些現在可以工作的代碼,而不需要花費過多的時間在「好」的方法上(這個兔子洞非常深),那麼你的解決方案就沒有問題。如果以這種方式使用庫函數數千次,那麼只需定義一些簡單的包裝,它們具有適當的一般類型,然後直接使用這些包裝來代替庫函數。 – user2407038

回答

0

如果你要處理的誤差只有一次,我會變換IO (Either e a)IO a與效用函數是這樣的:

throwWhenLeft :: Exception e => IO (Either e a) -> IO a 
throwWhenLeft io = either throwIO return =<< io 

這看起來很危險一目瞭然,但它的一些有用的(很常見,IMO)情況:

  • 你必須處理各種異常拋出/或者通過IO a或一些Either e a返回。
  • 異常處理程序的做法幾乎總是相同的。