2012-05-16 9 views
14

私はユーザー、グループ、およびユーザーとグループの間のマッピングのセットを持っています。私はこれらのセットを操作するさまざまな機能を持っていますが、存在しないユーザーにはグループ< - >グループマッピングを追加することはできません。また、メンバーをユーザーとして持つグループを削除しないでください。Haskellの「例外」

So基本的には、これらの関数が呼び出し側が明示的に処理しなければならない「例外」をスローする必要があります。

私が最初にこのような何かを返す考える:

data Return r e = Success r | Exception e 

を、呼び出し元がExceptionに対してパターンマッチをに失敗した場合、彼らはうまくいけば、コンパイラの警告を取得し、または非常に少なくとも明白なランタイムを持っています問題が発生した場合はエラーとなります。

これは最善のアプローチですか、これを行うパッケージ化されたソリューションがありますか?注:私はIO Monadではなく、純粋なコードで "例外"をスローして捕捉する必要があります。

答えて

19

はい、これは良いアプローチであり、標準ライブラリにあります。Return r eEither e rと同じです。 IOの例外を使用するようにコードを記述することもできます(つまり、パターンマッチングで各ステップのエラーを明示的に処理する必要はありません)。EitherMonadインスタンスは、Maybeと同じようにエラーを伝播します追加のeエラーの場合の値)。あまりにも、

data MyError 
    = Oops String 
    | VeryBadError Int Int 

mightFail :: T -> Either MyError Int 
mightFail a = ... 

foo :: T -> T -> Int -> Either MyError Int 
foo a b c = do 
    x <- mightFail a 
    y <- mightFail b 
    if x == y 
     then throwError (VeryBadError x y) 
     else return (x + y + c) 

mightFail a場合、またはmightFail b戻りLeft someError、そしてfoo a b c意志;例えば:エラーは自動的に伝播されます。 (ここでは、throwErrorControl.Monad.Errorから関数を使用して、Leftを書くだけの素敵な方法です;。catchErrorは、これらの例外をキャッチすることもあります)

11

あなたが記述しているReturn r eタイプが正確に標準タイプ

data Either a b = Left a | Right b 
です

mtlパッケージの、いわゆる"error monad"(より適切な名前は「例外モナド」)を使用するとよいでしょう。 (また、mtlを使用したくない場合は、monadLibパッケージにExceptionTがあります)。これにより、throwErrorcatchErrorを呼び出して、純粋なコードでエラー処理を行うことができます。 Here使用方法を示す例があります。

関連する問題