MonadFail
HaskellのMonadクラスには、returnと>>=に加え、もう一つのメソッド、fail :: Monad m => String -> m aが定義された。もともとは利便性のために作られたものだが、モナドの本質と無関係なばかりか、予期しないところでエラーになる危険性さえ生まれていた。それを解決するのがMonadFail Proposalだ。 fail概説
code:haskell
fail :: String -> m a
do文の脱糖に使用され、<- の左辺で部分的パターンマッチに失敗した場合に呼び出される。String引数にはコンパイラが生成したエラーメッセージが入る。
code:haskell
ghci> do { Just x <- return Nothing; putStrLn x}
*** Exception: user error (Pattern match failure in do expression at <interactive>:5:6-11)
このように、IOの場合は fail が呼ばれた時点で、与えられたエラーメッセージを吐いて終了する。普通の部分関数や部分的パターンマッチと同様、できれば避けるべきパターン。
一方MaybeやMaybeT、リスト、パーサコンビネータなどでは、失敗をさりげなく握りつぶす手段として使える。
code:haskell
ghci> sumHead2 l = do { x:y:_ <- return l; return (x+y) } :: Maybe Int
Just 3
Nothing
MonadFail Proposal以前は、すべてのモナドでfailを定義する必要があったが、上記のように上手く意味付けできるケースは限られていた。
結局、多くのモナドでデフォルトの定義、 error によるプログラム停止を採用せざるを得なかった。
序 《追加》 2016/02
GHC 8.0/base-4.9.0.0より。Monadからfailを切り離したMonadFailが追加された。追加されただけで特に警告が出たり何かが壊れたりするわけではないので、数年間誰も見向きもしなかった。
破 《脱糖》 2018/09
GHC 8.6/base-4.12.0.0より。do記法の中で部分的なパターンマッチをしている場合、MonadではなくMonadFailのfailを使うように変更された。また、警告-Wnoncanonical-monad-instancesにより、MonadがMonadFailと一致しないfailを定義している場合に警告を出せるようになった(デフォルトで出るとは言っていない)。
急 《削除》 2019/05?
ついにMonadからfailが除去される。failの定義に対する警告は明示的に指定しないと出ないし、そもそもfailの使用に関しては一切警告はなかったため、まさに青天の霹靂とともに藪から出てきた棒から寝耳に水が入ってきたかのようだ。
Haskell史上、もっとも多くのコードを壊滅させた変更と言っていいだろう。
ヴァンガード計画(Operation Vanguard)
主要な数百個のパッケージを一つにまとめ、一括でそれらすべてをビルドできるようにすることを狙うプロジェクト、ヴァンガード計画を進めている。 まとめ
MonadFail計画は進んでいたが、特に警告などはデフォルトでは出なかった
GHC 8.8/base-4.13で突如failが削除されるため、エコシステムは壊滅必至
正式リリースの前に主要なパッケージを修復するプロジェクト、ヴァンガード計画がほぼ完了