언제 어떤 기능을 사용합니까?
Control.Exception 설명서의 권장 사항은 다음과 같습니다.
- 예외가 발생한 경우 정리를 수행하려면
finally
, bracket
또는을 사용하십시오 onException
.
- 예외 후에 복구하고 다른 작업을 수행하려면
try
가족 중 하나를 사용하는 것이 가장 좋습니다 .
- ... 비동기 예외에서 복구하지 않는 한,이 경우
catch
또는 catchJust
.
try :: 예외 e => IO a-> IO (둘 중 하나)
try
소요 IO
실행에 조치를, 그리고를 반환합니다 Either
. 계산이 성공하면 결과가 Right
생성자에 래핑됩니다 . (잘못된 것이 아니라 옳다고 생각하십시오). 작업 에서 지정된 유형 의 예외 가 발생 하면 Left
생성자 에서 반환됩니다 . 예외가 적절한 유형 이 아닌 경우 스택 위로 계속 전파됩니다. SomeException
유형으로 지정 하면 모든 예외가 포착되며 이는 좋은 생각 일 수도 있고 아닐 수도 있습니다.
순수 계산에서 예외를 포착하려면을 사용 evaluate
하여 try
.
main = do
result <- try (evaluate (5 `div` 0)) :: IO (Either SomeException Int)
case result of
Left ex -> putStrLn $ "Caught exception: " ++ show ex
Right val -> putStrLn $ "The answer was: " ++ show val
catch :: 예외 e => IO a-> (e-> IO a)-> IO a
catch
와 유사합니다 try
. 먼저 지정된 IO
작업 을 실행하려고 시도 하지만 예외가 발생하면 처리기에 예외가 주어져 대체 응답을 얻습니다.
main = catch (print $ 5 `div` 0) handler
where
handler :: SomeException -> IO ()
handler ex = putStrLn $ "Caught exception: " ++ show ex
그러나 한 가지 중요한 차이점이 있습니다. catch
핸들러를 사용할 때 비동기 예외 (예 :를 통해 다른 스레드에서 발생)로 인해 중단 될 수 없습니다 throwTo
. 비동기 예외를 발생시키려는 시도는 핸들러 실행이 완료 될 때까지 차단됩니다.
catch
Prelude 에는 다른 기능 이 있으므로 import Prelude hiding (catch)
.
핸들 :: 예외 e => (e-> IO a)-> IO a-> IO a
handle
단순히 catch
반대 순서의 인수를 사용합니다. 사용할 코드는 코드를 더 읽기 쉽게 만드는 요소 또는 부분 응용 프로그램을 사용하려는 경우 어떤 것이 더 적합한 지에 따라 다릅니다. 그렇지 않으면 동일합니다.
tryJust, catchJust and handleJust
참고로 try
, catch
그리고 handle
잡을 것 모든 지정된 / 추론 유형의 예외. tryJust
친구를 사용하면 특별히 처리하려는 예외를 필터링하는 선택기 기능을 지정할 수 있습니다. 예를 들어, 모든 산술 오류는 유형 ArithException
입니다. 만 잡으려는 DivideByZero
경우 다음을 수행 할 수 있습니다.
main = do
result <- tryJust selectDivByZero (evaluate $ 5 `div` 0)
case result of
Left what -> putStrLn $ "Division by " ++ what
Right val -> putStrLn $ "The answer was: " ++ show val
where
selectDivByZero :: ArithException -> Maybe String
selectDivByZero DivideByZero = Just "zero"
selectDivByZero _ = Nothing
순결에 대한 참고 사항
이러한 유형의 예외 처리는 불순한 코드 (예 : IO
모나드) 에서만 발생할 수 있습니다 . 순수 코드에서 오류를 처리해야하는 경우 Maybe
또는 Either
대신 (또는 다른 대수 데이터 유형)을 사용하여 반환 값을 조사해야합니다 . 이것은 종종 더 명시 적이기 때문에 선호되므로 항상 어디서 일어날 수 있는지 알 수 있습니다. 모나드 Control.Monad.Error
는 이러한 유형의 오류 처리를 더 쉽게 사용할 수 있도록합니다.
또한보십시오: