여러 가지 문제가 있으므로 여기를 순서대로 살펴 보겠습니다. 위의와
MonadError e m => m()
문제는 e
어떤 식 으로든 제한되지 않은 경우,이 유형은 throwError
에 필요한 e
의 가치를 창출하는 것은 불가능하다는 것이다. 그래서 아니, 오류를 발생시킵니다 위의 유형에 대해 유일한 유효 값은 경찰 아웃 (매우 유용하지)이다
throwError undefined
을 포함해야합니다. Error e
제약 조건을 사용하면 문자열에서 e
유형의 값을 구성하는 메커니즘을 제공하여 e
을 추상 상태로 둘 수 있습니다.
어떤 상황에서 실패로 인해 생성 된 오류는 catchError로 처리 할 수 있습니까? catchError에 의해 실패하지 않을 수있는 원인은 무엇입니까?
이것은 전적으로 문제의 모나드에 따라 다릅니다. MonadError
의 다른 인스턴스는 fail
에 대해 다른 구현을 가질 수 있으므로 일반적인 대답은 없습니다. 또는 다른 말로하면, fail
에 의해 트리거 된 오류는 MonadError
의 특정 인스턴스를 사용하지 않는 한 catchError
으로 처리 할 수 있다는 보장이 없습니다. 예를 들어 main
의 첫 줄
{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.Error
example :: (Error e, MonadError e m) => m String
example = fail "This is a failure" `catchError` const (return "Error was caught")
main = do
example >>= putStrLn
either putStrLn putStrLn example
, example
는 IO
의 MonadError
인스턴스를 사용하여 두 번째 줄 Either String
의 MonadError
인스턴스를 사용한다.IO
에서 잡을 오류 fail
결과 아니지만 Either
너무 프로그램 출력 그러나
Error was caught
*** Exception: This is a failure
, 우리는 그 다음
example :: (Error e, MonadError e m) => m String
example = throwError (strMsg "This is a failure")
`catchError` const (return "Error was caught")
으로 example
교체하면 우리는 원하는 출력을 얻을
Error was caught
Error was caught
그리고 이것은 에 대해 동일하게 작동합니다. (유효한) 인스턴스 o f MonadError
, fail
과 다릅니다.
이러한 상황이 GHC 릴리스와 관련하여 어떤 방식으로 변경 되었습니까? (행동이 기본 4.3에서 변경 언급이 있습니다.) 기본 4.3
의 변화는 방법에 Either
모나드에서 fail
작품을 의미합니다. 이전 버전에서 fail
은 catchError
으로 잡히지 만, 이후에는 error
을 사용하고 IO
(예 : catch
)으로 처리해야하는 예외를 발생시키는 Left
값을 반환했습니다. 그것은 Either
모나드를 사용하고 (더 적합 Error
인스턴스가없는 경우 또는 단순히 Left
)는 throwError
를 사용해야하는 경우 fail
의 이전 동작을 가정처럼
Igor2의 문제는 소리가 난다.
'실패'가 'catchError'를 지나치는 작은 예제를 구성 할 수 있습니까? –
@Helmut : 간단한 예제가 추가되었습니다. – shang
GHC 7에서 Igor2 작업을 훨씬 더 잘할 수있게 해준 포괄적 인 대답을 보내 주셔서 대단히 감사합니다. 나는'throwError '로 잡힐 실패를 대체했습니다. strMsg'를 작성하고 필요에 따라 '오류 e'요구 사항을 도입했습니다. 다행스럽게도 관련 함수의 모든 사용자가 이미 추가 인스턴스를 제공했습니다. –