가장 단순한 MonadFail 인스턴스

6732 단어 haskell
일본어 버전은 はてなブログ 에 있습니다.


소개


failMonad 에서 오래 전에 제거된 후 MonadFail 에 실패할 수 있는 계산을 입력하는 것을 선호합니다.

foo :: MonadFail m => m a


이를 통해 m 컨텍스트 내에서 IOIO로 인스턴스화하고 순수 컨텍스트 내에서 Maybe로 인스턴스화할 수 있습니다.

-- within IO context
foo :: IO a

-- within pure context
foo :: Maybe a

Maybe 실패 메시지를 버리는 것은 기쁘지 않습니다. 그래서 우리는 Either를 사용해야 합니까? Either는 실제로 MonadFail 인스턴스가 아닙니다. 다음과 같은 이유로 거부된a proposal about this이(가) 있었습니다.

the instances "get in the way of a user who wants to treat the parameter uniformly"



그래서 가장 단순한Result 인스턴스로 다음MonadFail 유형을 원했습니다.

newtype Result a = Result (Either String a)

instance MonadFail Result where
  fail = Left


실제로 이와 동등한 것이 있지만 더 이상 사용되지 않습니다. mtl 패키지ErrorT입니다.

둘 중 하나의 결과 패키지


Result 및 일부 기능이 포함된 the either-result package을 출시했습니다.

https://hackage.haskell.org/package/either-result

실제로 ResultResultT Identity의 별칭이고 ResultT는 변압기 패키지의 ExceptT의 새로운 유형입니다.

type Result a = ResultT Identity a

newtype ResultT m a = ResultT (ExceptT String m a)

ResultTExceptT의 차이점은 대략 MonadFail 인스턴스입니다. On ResultT failLeft 로 메시지를 래핑하고, ExceptT 에서는 기본 모나드의 fail를 호출합니다. 이 때문에 ResultT 기본 모나드는 Monad 로 요청되지만 ExceptT 에서는 MonadFail 로 요청됩니다.

instance Monad m => MonadFail (ResultT m) where 

instance MonadFail m => MonadFail (ExceptT e m) where 

throwError는 mtl 패키지의 catchError 인스턴스이기 때문에 ResultTMonadError를 사용할 수 있습니다.

예외 패키지는 어떻습니까?


MonadThrow 타입 클래스가 있지 않습니까? 예, 예외 패키지에는 MonadThrowMonadCatch 유형 클래스가 있습니다. 이러한 요청은 Exception 인스턴스로 던져지고 포착됩니다. 내 생각에는 던진 것과 잡은 것을 종류별로 구분하고 싶다면 그것을 사용해야 한다. 그리고 메시지만 원하면 MonadFail 를 사용하십시오.

class Monad m => MonadThrow m where
  throwM :: Exception e => e -> m a

class MonadThrow m => MonadCatch m where
  catch :: Exception e => m a -> (e -> m a) -> m a

class Monad m => MonadFail m where
  fail :: String -> m a


결론


  • 정의할 때 실패할 수 있는 유형 계산MonadFail m => m a
  • 사용 시, IO a 컨텍스트 내에서 IO로 사용하십시오. 예를 들어
  • 사용시 순수 문맥
  • 내에서 Result a로 사용
  • 별을 the GitHub repository에 추가하세요 😉
  • 좋은 웹페이지 즐겨찾기