2011-12-22 86 views
5

我有處理哈斯克爾錯誤以下單子轉換。哈斯克爾單子和故障,不需要串

instance (Monad m, Error e) => Monad (EitherT e m) where 
    return = EitherT . return . return 
    m >>= k = EitherT $ do 
      a <- runEitherT m 
      case a of 
       Left l -> return (Left l) 
       Right r -> runEitherT (k r) 
    fail = EitherT . return . Left . strMsg 

它的工作原理相當不錯,因爲我可以實例Error與自定義類,並有由處理錯誤的一個非常靈活的手段。

fail雖然是有點愚蠢,因爲它是類型String -> EitherT e m,並且String限制可能是一個惱人的方式來創建錯誤。我結束了一大堆:

instance Error BazError where 
    strMsg "foo" = FooError -- oh look we have no error context 
    strMsg "bar" = BarError -- isn't that nice 

我希望做的是創建一個新的功能,如fail,即a -> e型的,這樣我可以刪除(Error e)限制。 fail是特別方便,當單子疊變大,當我結束了

EitherT BazError (StateT [BazWarning] IO) Foo 

像有沒有一種方法來創建具有相同的行爲fail用較少限制的類型的函數?或者fail採用深哈斯克爾黑暗魔法來實現?如果您在做塊有一個模式匹配失敗

+3

你或許應該簡單地避免'fail'完全,除非你要自定義的行爲對失敗'do'塊模式相匹配。 – ehird 2011-12-22 10:22:45

回答

7

好,fail叫,就像如果你有Just x <- somethingsomething的結果是Nothing。除此之外,fail是一個普通的功能。

對於strMsg "foo" = FooError等問題,throwError爲您的用例提供了一個更好的接口?

4

這篇文章可能是有用的:http://blog.ezyang.com/2011/08/8-ways-to-report-errors-in-haskell-revisited/

你EitherT已經在標準庫,並呼籲ErrorT。請參閱文檔:http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-Error.html#t:ErrorT

fail現在是一種歷史的好奇心,並且可能會考慮設計缺陷,並且缺乏Functor a => Monad a約束。這僅僅是一個有爭議的功能來處理失敗的格局do符號匹配。

throwError :: MonadError e m => e -> m a 

fail最常見的替代品,但更多的是可用的(見文章)。