2011-12-22 2 views
5

하스켈에서 오류를 처리하기 위해 다음과 같은 모나드 변환기가 있습니다. 나는 사용자 정의 클래스와 Error를 인스턴스화하고 오류를 처리하는 기준에 매우 유연한 수단을 가질 수하스켈 모나드와 문자열을 필요로하지 않는 실패

instance (Monad m, Error e) => Monad (EitherT e m) where 
    return = EitherT . return . return 
    m >>= k = EitherT $ do 
      a <- runEitherT m 
      case a of 
       Left l -> return (Left l) 
       Right r -> runEitherT (k r) 
    fail = EitherT . return . Left . strMsg 

그것은 꽤 잘 작동합니다.

fail은 다소 어리 석으며, 유형이 String -> EitherT e m이고 String 제한은 오류를 만드는 성가신 방법 일 수 있습니다. 나는 한꺼번에 많이와 끝까지 : 내가하고 싶은 무엇

instance Error BazError where 
    strMsg "foo" = FooError -- oh look we have no error context 
    strMsg "bar" = BarError -- isn't that nice 

은 내가 (Error e) 제한을 제거 할 수 있도록 유형 a -> e이며, fail 같은 새로운 기능을 만드는 것입니다. fail는 모나드 스택이 덜 제한적인 유형 fail과 같은 동작이있는 함수를 만들 수있는 방법이 있나요 내가

EitherT BazError (StateT [BazWarning] IO) Foo 

끝낼 때처럼 커질 때 특히 편리하다? 또는 deep haskell dark magic을 사용하여 fail을 구현 했습니까? 당신이 할 일 블록의 패턴 일치 고장이있는 경우 Just x <- something을 가지고있는 경우 something의 결과가 Nothing처럼

+3

실패한'do'-block 패턴 일치에 대한 동작을 사용자 정의하지 않으려면'fail' 만 피하십시오. – ehird

답변

7

음, fail가 호출됩니다. 그 외에도 fail은 일반적인 기능입니다.

strMsg "foo" = FooError 등의 문제에 대해 throwError은 사용 사례에 대해 더 멋진 인터페이스를 제공합니까?

4

이 문서에서는 유용 할 수 있습니다 : http://blog.ezyang.com/2011/08/8-ways-to-report-errors-in-haskell-revisited/

귀하의 EitherT는 표준 라이브러리에 이미와 ErrorT을했다. 설명서를 참조하십시오 : http://hackage.haskell.org/packages/archive/mtl/latest/doc/html/Control-Monad-Error.html#t:ErrorT

fail 지금 역사적 호기심, 그리고 Functor a => Monad a 제약의 부족과 함께, 디자인 결함으로 간주 할 수있다. do 표기법에서 실패한 패턴 일치를 처리하는 것은 논란의 여지가있는 기능입니다.

throwError :: MonadError e m => e -> m a 

fail에 대한 가장 일반적인 교체,하지만 더 많은 (기사 참조) 사용할 수 있습니다.