2014-01-07 5 views
1

그것은 catchError 취급 할 수있는 오류를 발생 MonadError E는 m @djinn => m()

MonadError e m => m() 

유형의 표현을 제공 할 수 있는가? Error e 요구 사항이 없음을 유의하십시오.

fail으로 만든 오류는 어떤 상황에서 catchError으로 처리 될 수 있습니까? 무엇이 catchError에 의해 잡히지 않고 fail으로 이어질 수 있습니까? GHC 공개와 관련하여 이러한 상황이 어떤 식으로 변화 했습니까? (동작베이스 4.3 변화하는 mention있다.)이 질문의 배경 코드의 큰 조각이다

에러 catchError 의해 fail "some message" 패스로 작성된 프로그램을 종료한다 (Igor2 함수 nomatch) 합성법 throwError undefined을 사용하여 fail을 호출하면 예상대로 오류가 잡히게됩니다. 물론 throwError undefined은 추한 해킹이며이 질문은 배경과 정확한 해결책을 이해하는 것을 목표로합니다.

답변

3

여러 가지 문제가 있으므로 여기를 순서대로 살펴 보겠습니다. 위의와

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 

, exampleIOMonadError 인스턴스를 사용하여 두 번째 줄 Either StringMonadError 인스턴스를 사용한다.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 작품을 의미합니다. 이전 버전에서 failcatchError으로 잡히지 만, 이후에는 error을 사용하고 IO (예 : catch)으로 처리해야하는 예외를 발생시키는 Left 값을 반환했습니다. 그것은 Either 모나드를 사용하고 (더 적합 Error 인스턴스가없는 경우 또는 단순히 Left)는 throwError를 사용해야하는 경우 fail의 이전 동작을 가정처럼

Igor2의 문제는 소리가 난다.

+0

'실패'가 'catchError'를 지나치는 작은 예제를 구성 할 수 있습니까? –

+1

@Helmut : 간단한 예제가 추가되었습니다. – shang

+0

GHC 7에서 Igor2 작업을 훨씬 더 잘할 수있게 해준 포괄적 인 대답을 보내 주셔서 대단히 감사합니다. 나는'throwError '로 잡힐 실패를 대체했습니다. strMsg'를 작성하고 필요에 따라 '오류 e'요구 사항을 도입했습니다. 다행스럽게도 관련 함수의 모든 사용자가 이미 추가 인스턴스를 제공했습니다. –

관련 문제