14

ユーザー、グループ、およびユーザーとグループ間のマッピングのセットがあります。これらのセットを操作するさまざまな関数がありますが、存在しないユーザーのユーザー <-> グループ マッピングを追加したり、ユーザーがまだメンバーとして含まれているグループを削除したりすることはできません。

したがって、基本的には、呼び出し元が明示的に処理する必要がある「例外」をこれらの関数でスローする必要があります。

私は最初に次のようなものを返すことを考えました:

data Return r e = Success r | Exception e

また、呼び出し元が に対するパターン マッチに失敗した場合Exception、コンパイラの警告が表示されるか、少なくとも問題が発生したときに明らかな実行時エラーが発生することが期待されます。

これは最善のアプローチですか? また、これを行うパッケージ化されたソリューションはありますか? IOモナドではなく、純粋なコードで「例外」をスローしてキャッチする必要があることに注意してください。

4

2 に答える 2

19

はい、これは良いアプローチであり、標準ライブラリにあります:Return r eは と同じEither e rです。で例外を使用するようにコードを書くこともできますIO(つまり、パターン マッチングを使用して各ステップでエラーを明示的に処理する必要はありません): のMonadインスタンスは、モナドEitherと同じようにエラーを伝播します (ただし、エラーの場合)。例えば:Maybee

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 someErrorfoo a b cthrowErrorLeftControl.Monad.ErrorcatchError

于 2012-05-16T02:59:01.323 に答える
11

あなたが説明しているReturn r eタイプはまさに標準タイプです

data Either a b = Left a | Right b

mtl パッケージのいわゆる「エラー モナド」 (より適切な名前は「例外モナド」) を使用することをお勧めします。(代わりにExceptionT、mtl を使用したくない場合は、monadLib パッケージに含まれています。) これにより、純粋なコードでthrowErrorandを呼び出してエラー処理を行うことができますcatchErrorここでは、その使用方法を示す例を見つけることができます。

于 2012-05-16T03:04:15.503 に答える