{-# LANGUAGE UndecidableInstances #-}

module Blucontrol.Gamma.Modifier (
  GammaModifierT
, runGammaModifierT
) where

import Control.Monad.Base
import Control.Monad.Except
import Control.Monad.Reader
import Control.Monad.Trans.Control

import Blucontrol.Gamma

newtype GammaModifierT c m a = GammaModifierT { GammaModifierT c m a -> ReaderT (c -> IO c) m a
unGammaModifierT :: ReaderT (c -> IO c) m a }
  deriving (Functor (GammaModifierT c m)
a -> GammaModifierT c m a
Functor (GammaModifierT c m)
-> (forall a. a -> GammaModifierT c m a)
-> (forall a b.
    GammaModifierT c m (a -> b)
    -> GammaModifierT c m a -> GammaModifierT c m b)
-> (forall a b c.
    (a -> b -> c)
    -> GammaModifierT c m a
    -> GammaModifierT c m b
    -> GammaModifierT c m c)
-> (forall a b.
    GammaModifierT c m a
    -> GammaModifierT c m b -> GammaModifierT c m b)
-> (forall a b.
    GammaModifierT c m a
    -> GammaModifierT c m b -> GammaModifierT c m a)
-> Applicative (GammaModifierT c m)
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m a
GammaModifierT c m (a -> b)
-> GammaModifierT c m a -> GammaModifierT c m b
(a -> b -> c)
-> GammaModifierT c m a
-> GammaModifierT c m b
-> GammaModifierT c m c
forall a. a -> GammaModifierT c m a
forall a b.
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m a
forall a b.
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
forall a b.
GammaModifierT c m (a -> b)
-> GammaModifierT c m a -> GammaModifierT c m b
forall a b c.
(a -> b -> c)
-> GammaModifierT c m a
-> GammaModifierT c m b
-> GammaModifierT c m c
forall c (m :: * -> *).
Applicative m =>
Functor (GammaModifierT c m)
forall c (m :: * -> *) a.
Applicative m =>
a -> GammaModifierT c m a
forall c (m :: * -> *) a b.
Applicative m =>
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m a
forall c (m :: * -> *) a b.
Applicative m =>
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
forall c (m :: * -> *) a b.
Applicative m =>
GammaModifierT c m (a -> b)
-> GammaModifierT c m a -> GammaModifierT c m b
forall c (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> GammaModifierT c m a
-> GammaModifierT c m b
-> GammaModifierT c m c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m a
$c<* :: forall c (m :: * -> *) a b.
Applicative m =>
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m a
*> :: GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
$c*> :: forall c (m :: * -> *) a b.
Applicative m =>
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
liftA2 :: (a -> b -> c)
-> GammaModifierT c m a
-> GammaModifierT c m b
-> GammaModifierT c m c
$cliftA2 :: forall c (m :: * -> *) a b c.
Applicative m =>
(a -> b -> c)
-> GammaModifierT c m a
-> GammaModifierT c m b
-> GammaModifierT c m c
<*> :: GammaModifierT c m (a -> b)
-> GammaModifierT c m a -> GammaModifierT c m b
$c<*> :: forall c (m :: * -> *) a b.
Applicative m =>
GammaModifierT c m (a -> b)
-> GammaModifierT c m a -> GammaModifierT c m b
pure :: a -> GammaModifierT c m a
$cpure :: forall c (m :: * -> *) a.
Applicative m =>
a -> GammaModifierT c m a
$cp1Applicative :: forall c (m :: * -> *).
Applicative m =>
Functor (GammaModifierT c m)
Applicative, a -> GammaModifierT c m b -> GammaModifierT c m a
(a -> b) -> GammaModifierT c m a -> GammaModifierT c m b
(forall a b.
 (a -> b) -> GammaModifierT c m a -> GammaModifierT c m b)
-> (forall a b. a -> GammaModifierT c m b -> GammaModifierT c m a)
-> Functor (GammaModifierT c m)
forall a b. a -> GammaModifierT c m b -> GammaModifierT c m a
forall a b.
(a -> b) -> GammaModifierT c m a -> GammaModifierT c m b
forall c (m :: * -> *) a b.
Functor m =>
a -> GammaModifierT c m b -> GammaModifierT c m a
forall c (m :: * -> *) a b.
Functor m =>
(a -> b) -> GammaModifierT c m a -> GammaModifierT c m b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> GammaModifierT c m b -> GammaModifierT c m a
$c<$ :: forall c (m :: * -> *) a b.
Functor m =>
a -> GammaModifierT c m b -> GammaModifierT c m a
fmap :: (a -> b) -> GammaModifierT c m a -> GammaModifierT c m b
$cfmap :: forall c (m :: * -> *) a b.
Functor m =>
(a -> b) -> GammaModifierT c m a -> GammaModifierT c m b
Functor, Applicative (GammaModifierT c m)
a -> GammaModifierT c m a
Applicative (GammaModifierT c m)
-> (forall a b.
    GammaModifierT c m a
    -> (a -> GammaModifierT c m b) -> GammaModifierT c m b)
-> (forall a b.
    GammaModifierT c m a
    -> GammaModifierT c m b -> GammaModifierT c m b)
-> (forall a. a -> GammaModifierT c m a)
-> Monad (GammaModifierT c m)
GammaModifierT c m a
-> (a -> GammaModifierT c m b) -> GammaModifierT c m b
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
forall a. a -> GammaModifierT c m a
forall a b.
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
forall a b.
GammaModifierT c m a
-> (a -> GammaModifierT c m b) -> GammaModifierT c m b
forall c (m :: * -> *). Monad m => Applicative (GammaModifierT c m)
forall c (m :: * -> *) a. Monad m => a -> GammaModifierT c m a
forall c (m :: * -> *) a b.
Monad m =>
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
forall c (m :: * -> *) a b.
Monad m =>
GammaModifierT c m a
-> (a -> GammaModifierT c m b) -> GammaModifierT c m b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> GammaModifierT c m a
$creturn :: forall c (m :: * -> *) a. Monad m => a -> GammaModifierT c m a
>> :: GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
$c>> :: forall c (m :: * -> *) a b.
Monad m =>
GammaModifierT c m a
-> GammaModifierT c m b -> GammaModifierT c m b
>>= :: GammaModifierT c m a
-> (a -> GammaModifierT c m b) -> GammaModifierT c m b
$c>>= :: forall c (m :: * -> *) a b.
Monad m =>
GammaModifierT c m a
-> (a -> GammaModifierT c m b) -> GammaModifierT c m b
$cp1Monad :: forall c (m :: * -> *). Monad m => Applicative (GammaModifierT c m)
Monad, MonadBase b, MonadBaseControl b, m a -> GammaModifierT c m a
(forall (m :: * -> *) a. Monad m => m a -> GammaModifierT c m a)
-> MonadTrans (GammaModifierT c)
forall c (m :: * -> *) a. Monad m => m a -> GammaModifierT c m a
forall (m :: * -> *) a. Monad m => m a -> GammaModifierT c m a
forall (t :: (* -> *) -> * -> *).
(forall (m :: * -> *) a. Monad m => m a -> t m a) -> MonadTrans t
lift :: m a -> GammaModifierT c m a
$clift :: forall c (m :: * -> *) a. Monad m => m a -> GammaModifierT c m a
MonadTrans, MonadTrans (GammaModifierT c)
m (StT (GammaModifierT c) a) -> GammaModifierT c m a
MonadTrans (GammaModifierT c)
-> (forall (m :: * -> *) a.
    Monad m =>
    (Run (GammaModifierT c) -> m a) -> GammaModifierT c m a)
-> (forall (m :: * -> *) a.
    Monad m =>
    m (StT (GammaModifierT c) a) -> GammaModifierT c m a)
-> MonadTransControl (GammaModifierT c)
(Run (GammaModifierT c) -> m a) -> GammaModifierT c m a
forall c. MonadTrans (GammaModifierT c)
forall c (m :: * -> *) a.
Monad m =>
m (StT (GammaModifierT c) a) -> GammaModifierT c m a
forall c (m :: * -> *) a.
Monad m =>
(Run (GammaModifierT c) -> m a) -> GammaModifierT c m a
forall (m :: * -> *) a.
Monad m =>
m (StT (GammaModifierT c) a) -> GammaModifierT c m a
forall (m :: * -> *) a.
Monad m =>
(Run (GammaModifierT c) -> m a) -> GammaModifierT c m a
forall (t :: (* -> *) -> * -> *).
MonadTrans t
-> (forall (m :: * -> *) a. Monad m => (Run t -> m a) -> t m a)
-> (forall (m :: * -> *) a. Monad m => m (StT t a) -> t m a)
-> MonadTransControl t
restoreT :: m (StT (GammaModifierT c) a) -> GammaModifierT c m a
$crestoreT :: forall c (m :: * -> *) a.
Monad m =>
m (StT (GammaModifierT c) a) -> GammaModifierT c m a
liftWith :: (Run (GammaModifierT c) -> m a) -> GammaModifierT c m a
$cliftWith :: forall c (m :: * -> *) a.
Monad m =>
(Run (GammaModifierT c) -> m a) -> GammaModifierT c m a
$cp1MonadTransControl :: forall c. MonadTrans (GammaModifierT c)
MonadTransControl)

instance MonadReader r m => MonadReader r (GammaModifierT c m) where
  ask :: GammaModifierT c m r
ask = m r -> GammaModifierT c m r
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m r
forall r (m :: * -> *). MonadReader r m => m r
ask
  local :: (r -> r) -> GammaModifierT c m a -> GammaModifierT c m a
local r -> r
f GammaModifierT c m a
tma = (Run (GammaModifierT c) -> m a) -> GammaModifierT c m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTransControl t, Monad m) =>
(Run t -> m a) -> t m a
liftWith ((Run (GammaModifierT c) -> m a) -> GammaModifierT c m a)
-> (Run (GammaModifierT c) -> m a) -> GammaModifierT c m a
forall a b. (a -> b) -> a -> b
$ \ Run (GammaModifierT c)
run ->
    (r -> r) -> m a -> m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local r -> r
f (m a -> m a) -> m a -> m a
forall a b. (a -> b) -> a -> b
$ GammaModifierT c m a -> m (StT (GammaModifierT c) a)
Run (GammaModifierT c)
run GammaModifierT c m a
tma

instance (MonadBase IO m, MonadGamma c m) => MonadGamma c (GammaModifierT c m) where
  gamma :: GammaModifierT c m c
gamma = do c
oldGamma <- m c -> GammaModifierT c m c
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m c
forall c (m :: * -> *). MonadGamma c m => m c
gamma
             c -> IO c
modifyGamma <- ReaderT (c -> IO c) m (c -> IO c) -> GammaModifierT c m (c -> IO c)
forall c (m :: * -> *) a.
ReaderT (c -> IO c) m a -> GammaModifierT c m a
GammaModifierT ReaderT (c -> IO c) m (c -> IO c)
forall r (m :: * -> *). MonadReader r m => m r
ask
             IO c -> GammaModifierT c m c
forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
liftBase (IO c -> GammaModifierT c m c) -> IO c -> GammaModifierT c m c
forall a b. (a -> b) -> a -> b
$ c -> IO c
modifyGamma c
oldGamma

runGammaModifierT :: (c -> IO c) -> GammaModifierT c m a -> m a
runGammaModifierT :: (c -> IO c) -> GammaModifierT c m a -> m a
runGammaModifierT c -> IO c
modify GammaModifierT c m a
tma = ReaderT (c -> IO c) m a -> (c -> IO c) -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (GammaModifierT c m a -> ReaderT (c -> IO c) m a
forall c (m :: * -> *) a.
GammaModifierT c m a -> ReaderT (c -> IO c) m a
unGammaModifierT GammaModifierT c m a
tma) c -> IO c
modify