{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-} 
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleInstances #-}
module Control.Monad.Chronicle.Class (
    MonadChronicle(..),
    ChronicleT(..), runChronicle
    ) where
import Data.These
import Data.These.Combinators
import Control.Applicative
import Control.Monad.Trans.Chronicle (ChronicleT, runChronicle)
import qualified Control.Monad.Trans.Chronicle as Ch
import Control.Monad.Trans.Identity as Identity
import Control.Monad.Trans.Maybe as Maybe
import Control.Monad.Trans.Error as Error
import Control.Monad.Trans.Except as Except
import Control.Monad.Trans.Reader as Reader
import Control.Monad.Trans.RWS.Lazy as LazyRWS
import Control.Monad.Trans.RWS.Strict as StrictRWS
import Control.Monad.Trans.State.Lazy as LazyState
import Control.Monad.Trans.State.Strict as StrictState
import Control.Monad.Trans.Writer.Lazy as LazyWriter
import Control.Monad.Trans.Writer.Strict as StrictWriter
import Control.Monad.Trans.Class (lift)
import Control.Monad (liftM)
import Data.Default.Class
import Data.Semigroup
import Prelude 
class (Monad m) => MonadChronicle c m | m -> c where
    
    
    
    dictate :: c -> m ()
    
    
    
    
    
    
    disclose :: (Default a) => c -> m a
    disclose c = dictate c >> return def
    
    
    
    confess :: c -> m a
    
    
    
    
    
    
    
    memento :: m a -> m (Either c a)
    
    
    
    absolve :: a -> m a -> m a
    
    
    
    
    
    condemn :: m a -> m a
    
    
    
    
    retcon :: (c -> c) -> m a -> m a
    
    chronicle :: These c a -> m a
instance (Semigroup c) => MonadChronicle c (These c) where
    dictate c = These c ()
    confess c = This c
    memento (This c) = That (Left c)
    memento m = mapThere Right m
    absolve x (This _) = That x
    absolve _ (That x) = That x
    absolve _ (These _ x) = That x
    condemn (These c _) = This c
    condemn m = m
    retcon = mapHere
    chronicle = id
instance (Semigroup c, Monad m) => MonadChronicle c (ChronicleT c m) where
    dictate = Ch.dictate
    confess = Ch.confess
    memento = Ch.memento
    absolve = Ch.absolve
    condemn = Ch.condemn
    retcon = Ch.retcon
    chronicle = Ch.ChronicleT . return
instance (MonadChronicle c m) => MonadChronicle c (IdentityT m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (IdentityT m) = lift $ memento m
    absolve x (IdentityT m) = lift $ absolve x m
    condemn (IdentityT m) = lift $ condemn m
    retcon f (IdentityT m) = lift $ retcon f m
    chronicle = lift . chronicle
instance (MonadChronicle c m) => MonadChronicle c (MaybeT m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (MaybeT m) = MaybeT $ either (Just . Left) (Right <$>) `liftM` memento m
    absolve x (MaybeT m) = MaybeT $ absolve (Just x) m
    condemn (MaybeT m) = MaybeT $ condemn m
    retcon f (MaybeT m) = MaybeT $ retcon f m
    chronicle = lift . chronicle
instance (Error e, MonadChronicle c m) => MonadChronicle c (ErrorT e m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (ErrorT m) = ErrorT $ either (Right . Left) (Right <$>) `liftM` memento m
    absolve x (ErrorT m) = ErrorT $ absolve (Right x) m
    condemn (ErrorT m) = ErrorT $ condemn m
    retcon f (ErrorT m) = ErrorT $ retcon f m
    chronicle = lift . chronicle
instance (MonadChronicle c m) => MonadChronicle c (ExceptT e m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (ExceptT m) = ExceptT $ either (Right . Left) (Right <$>) `liftM` memento m
    absolve x (ExceptT m) = ExceptT $ absolve (Right x) m
    condemn (ExceptT m) = ExceptT $ condemn m
    retcon f (ExceptT m) = ExceptT $ retcon f m
    chronicle = lift . chronicle
instance (MonadChronicle c m) => MonadChronicle c (ReaderT r m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (ReaderT m) = ReaderT $ memento . m
    absolve x (ReaderT m) = ReaderT $ absolve x . m
    condemn (ReaderT m) = ReaderT $ condemn . m
    retcon f (ReaderT m) = ReaderT $ retcon f . m
    chronicle = lift . chronicle
instance (MonadChronicle c m) => MonadChronicle c (LazyState.StateT s m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (LazyState.StateT m) = LazyState.StateT $ \s -> do
        either (\c -> (Left c, s)) (\(a, s') -> (Right a, s')) `liftM` memento (m s)
    absolve x (LazyState.StateT m) = LazyState.StateT $ \s -> absolve (x, s) $ m s
    condemn (LazyState.StateT m) = LazyState.StateT $ condemn . m
    retcon f (LazyState.StateT m) = LazyState.StateT $ retcon f . m
    chronicle = lift . chronicle
instance (MonadChronicle c m) => MonadChronicle c (StrictState.StateT s m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (StrictState.StateT m) = StrictState.StateT $ \s -> do
        either (\c -> (Left c, s)) (\(a, s') -> (Right a, s')) `liftM` memento (m s)
    absolve x (StrictState.StateT m) = StrictState.StateT $ \s -> absolve (x, s) $ m s
    condemn (StrictState.StateT m) = StrictState.StateT $ condemn . m
    retcon f (StrictState.StateT m) = StrictState.StateT $ retcon f . m
    chronicle = lift . chronicle
instance (Monoid w, MonadChronicle c m) => MonadChronicle c (LazyWriter.WriterT w m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (LazyWriter.WriterT m) = LazyWriter.WriterT $
        either (\c -> (Left c, mempty)) (\(a, w) -> (Right a, w)) `liftM` memento m
    absolve x (LazyWriter.WriterT m) = LazyWriter.WriterT $ absolve (x, mempty) m
    condemn (LazyWriter.WriterT m) = LazyWriter.WriterT $ condemn m
    retcon f (LazyWriter.WriterT m) = LazyWriter.WriterT $ retcon f m
    chronicle = lift . chronicle
instance (Monoid w, MonadChronicle c m) => MonadChronicle c (StrictWriter.WriterT w m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (StrictWriter.WriterT m) = StrictWriter.WriterT $
        either (\c -> (Left c, mempty)) (\(a, w) -> (Right a, w)) `liftM` memento m
    absolve x (StrictWriter.WriterT m) = StrictWriter.WriterT $ absolve (x, mempty) m
    condemn (StrictWriter.WriterT m) = StrictWriter.WriterT $ condemn m
    retcon f (StrictWriter.WriterT m) = StrictWriter.WriterT $ retcon f m
    chronicle = lift . chronicle
instance (Monoid w, MonadChronicle c m) => MonadChronicle c (LazyRWS.RWST r w s m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (LazyRWS.RWST m) = LazyRWS.RWST $ \r s ->
        either (\c -> (Left c, s, mempty)) (\(a, s', w) -> (Right a, s', w)) `liftM` memento (m r s)
    absolve x (LazyRWS.RWST m) = LazyRWS.RWST $ \r s -> absolve (x, s, mempty) $ m r s
    condemn (LazyRWS.RWST m) = LazyRWS.RWST $ \r s -> condemn $ m r s
    retcon f (LazyRWS.RWST m) = LazyRWS.RWST $ \r s -> retcon f $ m r s
    chronicle = lift . chronicle
instance (Monoid w, MonadChronicle c m) => MonadChronicle c (StrictRWS.RWST r w s m) where
    dictate = lift . dictate
    confess = lift . confess
    memento (StrictRWS.RWST m) = StrictRWS.RWST $ \r s ->
        either (\c -> (Left c, s, mempty)) (\(a, s', w) -> (Right a, s', w)) `liftM` memento (m r s)
    absolve x (StrictRWS.RWST m) = StrictRWS.RWST $ \r s -> absolve (x, s, mempty) $ m r s
    condemn (StrictRWS.RWST m) = StrictRWS.RWST $ \r s -> condemn $ m r s
    retcon f (StrictRWS.RWST m) = StrictRWS.RWST $ \r s -> retcon f $ m r s
    chronicle = lift . chronicle