2011-12-22 11 views
5

私はHaskellでエラーを処理するために次のモナドトランスフォーマーを持っています。Haskellモナドと文字列を必要としないフェイル

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という制限がエラーを作成する厄介な方法になる可能性があるため、少しばかです。私は何をしたいのですが、私は(Error e)制限を解除することができるようfailのように、それはタイプa -> eであり、新しい関数を作成することです

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

:私はの全体の多くで終わります。 failはモナドスタックがより制限の少ないタイプでfailと同じ動作を持つ関数を作成する方法はあります私は

EitherT BazError (StateT [BazWarning] IO) Foo 

で終わるときのように、大きくなる場合には特に便利なのですか?または深いhaskell暗い魔法を使用してfailが実装されていますか?

+3

失敗した 'do'-blockパターンマッチの振る舞いをカスタマイズしない限り、単に' fail'を完全に避けるべきでしょう。 – ehird

答えて

7

あなたがブロック内のパターン照合障害が発生した場合は、Just x <- somethingを持っているとsomethingの結果はNothingであるかのようにまあ、failは、と呼ばれています。それ以外は、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のための最も一般的な代替ですが、より多くの(記事を参照)があります。

関連する問題