Control.Monad.Trans.Control がよくわからないのでいろいろ調べてみた。
MonadTransControl がやりたいのは、MaybeTとrunMaybeT、もしくはListTとrunListT、のようにXxxxTとrunXxxxTの組の操作を抽象化したいということだと思われる。
例えば、MaybeT [] aにreverseを適用したい場合、MaybeT [] aは[Maybe a]のことなので、runMaybeTでラップを外してリストを処理してからMaybeTで再ラップすることで以下のように書ける。
reverseMaybeT :: MaybeT [] a -> MaybeT [] a
reverseMaybeT = MaybeT . reverse . runMaybeT
MonadTransControl型クラスを使えば、reverseMaybeTを様々なモナド変換子に対して一般的に定義できる。
reverseT :: (Monad (t []), MonadTransControl t) => t [] a -> t [] a
reverseT t = liftWith (\run -> reverse $ run t) >>= restoreT . return
runがrunMaybeT、restoreTがMaybeT(コンストラクタ)、StT tはMaybeの役割を果たす。run tによってラップを剥がしてリストにしてくれるのだが、その型は当然tによって違い[StT t a]のような型で返ってくるので、総称的にリストを操作する関数だけが利用できる。
ちなみにreverseTの定義の末尾のreturnが非常に気持ち悪いのだけど、これはどう解釈すればいいんだろ。型を見れば必要なのはわかるんだけど、最初のreverseMaybeTの定義と比較すると乖離が激しくて、ちょっと気持ち悪い。
ここまでわかれば、MonadBaseControl型クラスもMonadTransControlとほぼ同じ物と見なせばいいと思う。MonadIOが重要なのと同様に、MonadBaseControlの方が用途は広い気がする。