{-# Language RankNTypes #-}
{-# Language FlexibleInstances #-}
{-# Language ScopedTypeVariables #-}
{-# Language UndecidableInstances #-}
{-# Language MultiParamTypeClasses #-}
module Control.Monad.Trans.Choice.Invariant
  ( ChoiceT
    ( ChoiceT
    )
  , runChoiceT
  , invmapChoiceT
  ) where
import Control.Monad.Class.Choice
  ( MonadChoice
  , choose
  )
import Control.Applicative
  ( Alternative
    ( empty
    , (<|>)
    )
  )
import Control.Monad.Except
  ( MonadError
    ( throwError
    , catchError
    )
  )
import Control.Monad
  ( MonadPlus
  )
import Control.Monad.IO.Class
  ( MonadIO
    ( liftIO
    )
  )
import Control.Monad.Reader.Class
  ( MonadReader
    ( ask
    , local
    )
  )
import Control.Monad.State.Class
  ( MonadState
    ( get
    , put
    )
  )
import Control.Monad.Trans
  ( MonadTrans
  , lift
  )
import Control.Monad.Writer.Class
  ( MonadWriter
    ( listen
    , pass
    , tell
    )
  )
import Data.Functor.Contravariant
  ( Contravariant
    ( contramap
    )
  )
import Data.Functor.Invariant
  ( Invariant
    ( invmap
    )
  )
newtype ChoiceT f m a = ChoiceT
  { _runChoiceT :: (forall x . f x -> m x) -> m a
  
  
  }
invmapChoiceT ::
  (forall x . n x -> m x)
    -> (m a -> n b)
      -> ChoiceT f m a
        -> ChoiceT f n b
invmapChoiceT f g m1 = ChoiceT (\ chooser -> g $ runChoiceT (\ options -> f $ chooser options) m1)
runChoiceT ::
  (forall x . f x -> m x)
  
  
  
  
  
  
    -> ChoiceT f m a
    
      -> m a
      
runChoiceT chooser m1 = _runChoiceT m1 chooser
lowMap ::
  (m a -> m b)
    -> (ChoiceT f m a -> ChoiceT f m b)
lowMap f m = ChoiceT (\ chooser -> f $ runChoiceT chooser m)
instance Functor m => Functor (ChoiceT f m) where
  fmap f (ChoiceT deChooser) = ChoiceT (\ chooser -> fmap f $ deChooser chooser)
instance Contravariant m => Contravariant (ChoiceT f m) where
  contramap f (ChoiceT deChooser) = ChoiceT (\ chooser -> contramap f $ deChooser chooser)
instance Invariant m => Invariant (ChoiceT f m) where
  invmap f1 f2 (ChoiceT deChooser) = ChoiceT (\ chooser -> invmap f1 f2 $ deChooser chooser)
instance Applicative m => Applicative (ChoiceT f m) where
  pure a =
    ChoiceT (\ _ -> pure a )
  (ChoiceT lDeChooser) <*> (ChoiceT rDeChooser) =
    ChoiceT (\ chooser -> lDeChooser chooser <*> rDeChooser chooser )
instance Alternative m => Alternative (ChoiceT f m) where
  empty = ChoiceT (const empty)
  m1 <|> m2 = ChoiceT (\ chooser -> runChoiceT chooser m1 <|> runChoiceT chooser m2)
instance Monad m => Monad (ChoiceT f m) where
  (ChoiceT deChooser) >>= f =
    ChoiceT (\ chooser -> deChooser chooser >>= (\ x -> runChoiceT chooser (f x)) )
instance MonadPlus m => MonadPlus (ChoiceT f m)
instance MonadTrans (ChoiceT f) where
  lift m = ChoiceT (\ _ -> m )
instance Monad m => MonadChoice f (ChoiceT f m) where
  choose f = ChoiceT (\ chooser -> chooser f )
instance MonadReader r m => MonadReader r (ChoiceT f m) where
  ask = lift ask
  local f = lowMap (local f)
instance MonadState s m => MonadState s (ChoiceT f m) where
  get = lift get
  put s = lift (put s)
instance MonadWriter w m => MonadWriter w (ChoiceT f m) where
  tell w = lift (tell w)
  listen = lowMap listen
  pass   = lowMap pass
instance MonadIO m => MonadIO (ChoiceT f m) where
  liftIO = lift . liftIO
instance MonadError e m => MonadError e (ChoiceT f m) where
  throwError toThrow = lift (throwError toThrow)
  catchError m handler = ChoiceT (\ chooser -> catchError (runChoiceT chooser m) (runChoiceT chooser . handler))