モナド変換子を作ってみるやつのMaybeT、写経してみたけどうまく動かなくて四苦八苦した結果のメモ書き
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-} module MaybeT where import Control.Monad.Trans import Control.Monad.State newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } altBindMT :: Monad m => MaybeT m a -> (a -> MaybeT m b) -> MaybeT m b x `altBindMT` f = MaybeT $ runMaybeT x >>= maybe (return Nothing) (runMaybeT . f) instance (Functor f) => Functor (MaybeT f) where fmap = undefined instance (Applicative a) => Applicative (MaybeT a) where pure = undefined (<*>) = undefined instance (Monad m) => Monad (MaybeT m) where return a = MaybeT $ return (Just a) (>>=) = altBindMT fail _ = MaybeT $ return Nothing instance MonadTrans MaybeT where lift = lift instance (MonadIO m) => MonadIO (MaybeT m) where liftIO m = lift (liftIO m) instance (MonadState s m) => MonadState s (MaybeT m) where get = lift get put k = lift (put k)
要はアプリカティブとファンクタのインスタンスをundefinedでサボってでもやっとけばコンパイルが通るように。
それぞれちゃんと書いてみたのが以下
liftA2MT :: (Applicative a) => MaybeT a (b -> c) -> MaybeT a b -> MaybeT a c af `liftA2MT` ax = MaybeT $ fmap (<*>) (runMaybeT af) <*> runMaybeT ax instance (Functor f) => Functor (MaybeT f) where fmap f a = MaybeT $ fmap (fmap f) (runMaybeT a) instance (Applicative a) => Applicative (MaybeT a) where pure a = MaybeT $ pure (Just a) (<*>) = liftA2MT
UglyStackの方はどう治せば綺麗に動くのかなぁ?