けいぞうのメモ帳

言語設計のお勉強

Data.Binary.GetのGet MonadにおけるMonadFail

できること

Get Monadの中でControl.Monad.Fail.failを実行すると、runGetOrFailのときにLeftを取ることが出来る。 runGetOrFailが取る引数はユーザが定義した任意の構造体へのdecoderであるGet Monadのため、 Get Monadの失敗をユーザがハンドルできる。

MonadFail

モナドの中での失敗を意味する型クラス。 もともとはMonadのメソッドだったところを「分離していいよね?」という提案の元、型クラスに分離された経緯がある。

ref:

Control.Monad.Fail

PoC

{-# LANGUAGE OverloadedStrings #-}
module Main where


import           Data.Binary.Get

main :: IO ()
main = print $ f

f = case (runGetOrFail decode "") of
      Right (rest, _,f) -> ""
      Left _            -> "runGetOrFail return Left when called in Get Monad"


data Sample = Sample Int
            deriving Show

decode :: Get Sample
decode = fail "you shoul fail"

b読み飛ばしても良い経緯

inary packageのData.Binary.Getを正常に失敗させる方法を知りたい。
binary packageのData.Binary.Get.runGetOrFailでは 失敗するかもしれないGetモナドを実行することができる。 これをユーザがハンドルする方法がドキュメントに書いてなかった。 しかしGetモナドはMonadFailのインスタンスであり、MonadFailは モナドの失敗を扱うことが出来る型クラスであるためこれを用いたときに、失敗時の処理となるのではないかと思った。