packages feed

monad-abort-fd-0.2: src/Control/Monad/Finish/Class.hs

{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Control.Monad.Finish.Class (
    MonadFinish(..)
  ) where

import Data.Monoid
import Control.Monad.Trans.Identity
import Control.Monad.Trans.Maybe
import Control.Monad.Cont
import Control.Monad.Error
import Control.Monad.List
import Control.Monad.Reader
import Control.Monad.State (MonadState(..))
import qualified Control.Monad.State.Lazy as L
import qualified Control.Monad.State.Strict as S
import Control.Monad.Writer (MonadWriter(..))
import qualified Control.Monad.Writer.Lazy as L
import qualified Control.Monad.Writer.Strict as S
import Control.Monad.RWS (MonadRWS)
import qualified Control.Monad.RWS.Lazy as L
import qualified Control.Monad.RWS.Strict as S
import Control.Monad.Abort
import Control.Monad.Trans.Finish (FinishT(..))
import qualified Control.Monad.Trans.Finish as F

class Monad μ ⇒ MonadFinish f μ | μ → f where
  finish ∷ f → μ α

instance Monad μ ⇒ MonadFinish f (FinishT f μ) where
  finish = F.finish

instance MonadCont μ ⇒ MonadCont (FinishT f μ) where
  callCC k = FinishT $ callCC $ \f → runFinishT $ k (lift . f . Right) 

instance MonadError e μ ⇒ MonadError e (FinishT f μ) where
  throwError = lift . throwError
  catchError m h = FinishT $ catchError (runFinishT m) (runFinishT . h)

instance MonadAbort e μ ⇒ MonadAbort e (FinishT f μ) where
  abort = lift . abort

instance MonadRecover e μ ⇒ MonadRecover e (FinishT f μ) where
  recover m h = FinishT $ recover (runFinishT m) (runFinishT . h)

instance MonadReader r μ ⇒ MonadReader r (FinishT f μ) where
  ask = lift ask
  local f = FinishT . local f . runFinishT

instance MonadState s μ ⇒ MonadState s (FinishT f μ) where
  get = lift get
  put = lift . put

instance MonadWriter w μ ⇒ MonadWriter w (FinishT f μ) where
  tell = lift . tell
  listen m = FinishT $ do
    (lr, w) ← listen $ runFinishT m
    return $! fmap (, w) lr
  pass m = FinishT $ pass $ do
    lr ← runFinishT m
    return $! either ((, id) . Left) (\(r, f) → (Right r, f)) lr

instance MonadRWS r w s μ ⇒ MonadRWS r w s (FinishT f μ)

instance MonadFinish f μ ⇒ MonadFinish f (IdentityT μ) where
  finish = lift . finish

instance MonadFinish f μ ⇒ MonadFinish f (ContT r μ) where
  finish = lift . finish

instance MonadFinish f μ ⇒ MonadFinish f (MaybeT μ) where
  finish = lift . finish

instance (MonadFinish f μ, Error e) ⇒ MonadFinish f (ErrorT e μ) where
  finish = lift . finish

instance MonadFinish f μ ⇒ MonadFinish f (AbortT e μ) where
  finish = lift . finish

instance MonadFinish f μ ⇒ MonadFinish f (ListT μ) where
  finish = lift . finish

instance MonadFinish f μ ⇒ MonadFinish f (ReaderT r μ) where
  finish = lift . finish

instance MonadFinish f μ ⇒ MonadFinish f (L.StateT s μ) where
  finish = lift . finish

instance MonadFinish f μ ⇒ MonadFinish f (S.StateT s μ) where
  finish = lift . finish

instance (MonadFinish f μ, Monoid w) ⇒ MonadFinish f (L.WriterT w μ) where
  finish = lift . finish

instance (MonadFinish f μ, Monoid w) ⇒ MonadFinish f (S.WriterT w μ) where
  finish = lift . finish

instance (MonadFinish f μ, Monoid w) ⇒ MonadFinish f (L.RWST r w s μ) where
  finish = lift . finish

instance (MonadFinish f μ, Monoid w) ⇒ MonadFinish f (S.RWST r w s μ) where
  finish = lift . finish