2012-05-16 2 views
14

나는 사용자, 그룹 및 사용자와 그룹 간의 매핑을 가지고있다. 이 세트를 조작하는 다양한 기능이 있지만 존재하지 않는 사용자에 대해 그룹을 매핑하거나 사용자를 추가 할 수 없어야합니다.하스켈의 "예외"

So 기본적으로 나는 이러한 함수가 호출자가 명시 적으로 처리해야하는 "예외"를 throw하려고합니다.

는 내가 처음이 같은 반환 생각 :

data Return r e = Success r | Exception e 

을 그리고 호출자가 Exception에 대한 패턴 일치, 그들은 희망 컴파일러 경고를 얻을 수 있습니다하지 못하는 경우, 또는 적어도 확실한 실행을 문제가 발생하면 오류가 발생합니다.

이 방법이 가장 좋은 방법이며이를 위해 미리 패키지 된 솔루션이 있습니까? 참고 : IO Monad가 아니라 순수한 코드에서 "예외"를 포착하고 catch해야합니다.

답변

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 의지; 오류는 자동으로 전달됩니다. (여기서, throwErrorLeft를 작성 Control.Monad.Error에서 함수를 사용하여 단지 좋은 방법이며, 이러한 예외를 잡기도 catchError이 있습니다.) 당신이 묘사하는

11

Return r e 유형은 정확히 표준 타입

data Either a b = Left a | Right b 
입니다

mtl 패키지의 "error monad" (보다 적합한 이름은 "예외적 인 모나드")을 사용할 수 있습니다. (또는 mtl을 사용하지 않으려면 monadLib 패키지에 ExceptionT이 있습니다.) 이렇게하면 throwErrorcatchError을 호출하여 순수 코드에서 오류 처리를 수행 할 수 있습니다. Here 사용법을 보여주는 예제를 찾을 수 있습니다.