5

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制限がエラーを作成するための厄介な方法になる可能性があるため、少しばかげています。私はたくさんのことになります:

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、ディープハスケルダークマジックを使用して実装されていますか?

4

2 に答える 2

7

さて、failあなたが持っている場合のように、doブロックでパターンマッチの失敗があった場合に呼び出され、Just x <- somethingsomething結果はNothingです。それとは別にfail、通常の機能です。

strMsg "foo" = FooErroretcの問題についてはthrowError、ユースケースに適したインターフェイスを提供していますか?

于 2011-12-22T10:08:09.880 に答える
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

failFunctor a => Monad aは現在の歴史的な好奇心であり、制約の欠如とともに、設計上の欠陥と見なされる可能性があります。do表記法で失敗したパターン一致を処理することは、物議を醸す機能にすぎません。

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

の最も一般的な代替品ですfailが、さらに多くの製品が利用可能です(記事を参照)。

于 2011-12-22T13:27:24.623 に答える