    {-# LANGUAGE CPP #-}
    {-# LANGUAGE FlexibleContexts #-}
    #if __GLASGOW_HASKELL__ >= 707
    {-# LANGUAGE StandaloneDeriving, DeriveDataTypeable, Safe #-}
    #elif __GLASGOW_HASKELL__ >= 702
    {-# LANGUAGE Trustworthy #-}
    #endif
    #ifndef MIN_VERSION_base
    #define MIN_VERSION_base(x,y,z) 1
    #endif
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Control.Comonad.Trans.Env
    -- Copyright   :  (C) 2008-2013 Edward Kmett
    -- License     :  BSD-style (see the file LICENSE)
    --
    -- Maintainer  :  Edward Kmett <ekmett@gmail.com>
    -- Stability   :  provisional
    -- Portability :  portable
    --
    -- The environment comonad holds a value along with some retrievable context.
    --
    -- This module specifies the environment comonad transformer (aka coreader),
    -- which is left adjoint to the reader comonad.
    --
    -- The following sets up an experiment that retains its initial value in the
    -- background:
    --
    -- >>> let initial = env 0 0
    --
    -- Extract simply retrieves the value:
    --
    -- >>> extract initial
    -- 0
    --
    -- Play around with the value, in our case producing a negative value:
    --
    -- >>> let experiment = fmap (+ 10) initial
    -- >>> extract experiment
    -- 10
    --
    -- Oh noes, something went wrong, 10 isn't very negative! Better restore the
    -- initial value using the default:
    --
    -- >>> let initialRestored = experiment =>> ask
    -- >>> extract initialRestored
    -- 0
    ----------------------------------------------------------------------------
    module Control.Comonad.Trans.Env
      (
      -- * The strict environment comonad
        Env
      , env
      , runEnv
      -- * The strict environment comonad transformer
      , EnvT(..)
      , runEnvT
      , lowerEnvT
      -- * Combinators
      , ask
      , asks
      , local
      ) where

    #if !(MIN_VERSION_base(4,8,0))
    import Control.Applicative
    #endif
    import Control.Comonad
    import Control.Comonad.Hoist.Class
    import Control.Comonad.Trans.Class
    #if __GLASGOW_HASKELL__ < 710
    import Data.Foldable
    import Data.Traversable
    #endif
    import Data.Functor.Identity
    #if !(MIN_VERSION_base(4,11,0))
    import Data.Semigroup
    #endif

    #ifdef __GLASGOW_HASKELL__
    #if __GLASGOW_HASKELL__ >= 707
    #define Typeable1 Typeable
    #endif
    import Data.Data

    #if __GLASGOW_HASKELL__ >= 707
    deriving instance Typeable EnvT
    #else
    instance (Typeable s, Typeable1 w) => Typeable1 (EnvT s w) where
      typeOf1 dswa = mkTyConApp envTTyCon [typeOf (s dswa), typeOf1 (w dswa)]
        where
          s :: EnvT s w a -> s
          s = undefined
          w :: EnvT s w a -> w a
          w = undefined

    envTTyCon :: TyCon
    #if __GLASGOW_HASKELL__ < 704
    envTTyCon = mkTyCon "Control.Comonad.Trans.Env.EnvT"
    #else
    envTTyCon = mkTyCon3 "comonad-transformers" "Control.Comonad.Trans.Env" "EnvT"
    #endif
    {-# NOINLINE envTTyCon #-}

    #endif

    #if __GLASGOW_HASKELL__ < 707
    instance (Typeable s, Typeable1 w, Typeable a) => Typeable (EnvT s w a) where
      typeOf = typeOfDefault
    #endif

    instance
      ( Data e
      , Typeable1 w, Data (w a)
      , Data a
      ) => Data (EnvT e w a) where
        gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> EnvT e w a -> c (EnvT e w a)
    gfoldl f :: forall d b. Data d => c (d -> b) -> d -> c b
    f z :: forall g. g -> c g
    z (EnvT e :: e
    e wa :: w a
    wa) = (e -> w a -> EnvT e w a) -> c (e -> w a -> EnvT e w a)
    forall g. g -> c g
    z e -> w a -> EnvT e w a
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT c (e -> w a -> EnvT e w a) -> e -> c (w a -> EnvT e w a)
    forall d b. Data d => c (d -> b) -> d -> c b
    `f` e
    e c (w a -> EnvT e w a) -> w a -> c (EnvT e w a)
    forall d b. Data d => c (d -> b) -> d -> c b
    `f` w a
    wa
        toConstr :: EnvT e w a -> Constr
    toConstr _ = Constr
    envTConstr
        gunfold :: (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c (EnvT e w a)
    gunfold k :: forall b r. Data b => c (b -> r) -> c r
    k z :: forall r. r -> c r
    z c :: Constr
    c = case Constr -> Int
    constrIndex Constr
    c of
            1 -> c (w a -> EnvT e w a) -> c (EnvT e w a)
    forall b r. Data b => c (b -> r) -> c r
    k (c (e -> w a -> EnvT e w a) -> c (w a -> EnvT e w a)
    forall b r. Data b => c (b -> r) -> c r
    k ((e -> w a -> EnvT e w a) -> c (e -> w a -> EnvT e w a)
    forall r. r -> c r
    z e -> w a -> EnvT e w a
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT))
            _ -> [Char] -> c (EnvT e w a)
    forall a. HasCallStack => [Char] -> a
    error "gunfold"
        dataTypeOf :: EnvT e w a -> DataType
    dataTypeOf _ = DataType
    envTDataType
        dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c (EnvT e w a))
    dataCast1 f :: forall d. Data d => c (t d)
    f = c (t a) -> Maybe (c (EnvT e w a))
    forall k1 k2 (c :: k1 -> *) (t :: k2 -> k1) (t' :: k2 -> k1)
           (a :: k2).
    (Typeable t, Typeable t') =>
    c (t a) -> Maybe (c (t' a))
    gcast1 c (t a)
    forall d. Data d => c (t d)
    f

    envTConstr :: Constr
    envTConstr :: Constr
    envTConstr = DataType -> [Char] -> [[Char]] -> Fixity -> Constr
    mkConstr DataType
    envTDataType "EnvT" [] Fixity
    Prefix
    {-# NOINLINE envTConstr #-}

    envTDataType :: DataType
    envTDataType :: DataType
    envTDataType = [Char] -> [Constr] -> DataType
    mkDataType "Control.Comonad.Trans.Env.EnvT" [Constr
    envTConstr]
    {-# NOINLINE envTDataType #-}

    #endif

    type Env e = EnvT e Identity
    data EnvT e w a = EnvT e (w a)

    -- | Create an Env using an environment and a value
    env :: e -> a -> Env e a
    env :: e -> a -> Env e a
    env e :: e
    e a :: a
    a = e -> Identity a -> Env e a
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT e
    e (a -> Identity a
    forall a. a -> Identity a
    Identity a
    a)

    runEnv :: Env e a -> (e, a)
    runEnv :: Env e a -> (e, a)
    runEnv (EnvT e :: e
    e (Identity a :: a
    a)) = (e
    e, a
    a)

    runEnvT :: EnvT e w a -> (e, w a)
    runEnvT :: EnvT e w a -> (e, w a)
    runEnvT (EnvT e :: e
    e wa :: w a
    wa) = (e
    e, w a
    wa)

    instance Functor w => Functor (EnvT e w) where
      fmap :: (a -> b) -> EnvT e w a -> EnvT e w b
    fmap g :: a -> b
    g (EnvT e :: e
    e wa :: w a
    wa) = e -> w b -> EnvT e w b
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT e
    e ((a -> b) -> w a -> w b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap a -> b
    g w a
    wa)

    instance Comonad w => Comonad (EnvT e w) where
      duplicate :: EnvT e w a -> EnvT e w (EnvT e w a)
    duplicate (EnvT e :: e
    e wa :: w a
    wa) = e -> w (EnvT e w a) -> EnvT e w (EnvT e w a)
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT e
    e ((w a -> EnvT e w a) -> w a -> w (EnvT e w a)
    forall (w :: * -> *) a b. Comonad w => (w a -> b) -> w a -> w b
    extend (e -> w a -> EnvT e w a
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT e
    e) w a
    wa)
      extract :: EnvT e w a -> a
    extract (EnvT _ wa :: w a
    wa) = w a -> a
    forall (w :: * -> *) a. Comonad w => w a -> a
    extract w a
    wa

    instance ComonadTrans (EnvT e) where
      lower :: EnvT e w a -> w a
    lower (EnvT _ wa :: w a
    wa) = w a
    wa

    instance (Monoid e, Applicative m) => Applicative (EnvT e m) where
      pure :: a -> EnvT e m a
    pure = e -> m a -> EnvT e m a
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT e
    forall a. Monoid a => a
    mempty (m a -> EnvT e m a) -> (a -> m a) -> a -> EnvT e m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
      EnvT ef :: e
    ef wf :: m (a -> b)
    wf <*> :: EnvT e m (a -> b) -> EnvT e m a -> EnvT e m b
    <*> EnvT ea :: e
    ea wa :: m a
    wa = e -> m b -> EnvT e m b
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT (e
    ef e -> e -> e
    forall a. Monoid a => a -> a -> a
    `mappend` e
    ea) (m (a -> b)
    wf m (a -> b) -> m a -> m b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> m a
    wa)

    -- | Gets rid of the environment. This differs from 'extract' in that it will
    --   not continue extracting the value from the contained comonad.
    lowerEnvT :: EnvT e w a -> w a
    lowerEnvT :: EnvT e w a -> w a
    lowerEnvT (EnvT _ wa :: w a
    wa) = w a
    wa

    instance ComonadHoist (EnvT e) where
      cohoist :: (forall x. w x -> v x) -> EnvT e w a -> EnvT e v a
    cohoist l :: forall x. w x -> v x
    l (EnvT e :: e
    e wa :: w a
    wa) = e -> v a -> EnvT e v a
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT e
    e (w a -> v a
    forall x. w x -> v x
    l w a
    wa)

    instance (Semigroup e, ComonadApply w) => ComonadApply (EnvT e w) where
      EnvT ef :: e
    ef wf :: w (a -> b)
    wf <@> :: EnvT e w (a -> b) -> EnvT e w a -> EnvT e w b
    <@> EnvT ea :: e
    ea wa :: w a
    wa = e -> w b -> EnvT e w b
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT (e
    ef e -> e -> e
    forall a. Semigroup a => a -> a -> a
    <> e
    ea) (w (a -> b)
    wf w (a -> b) -> w a -> w b
    forall (w :: * -> *) a b.
    ComonadApply w =>
    w (a -> b) -> w a -> w b
    <@> w a
    wa)

    instance Foldable w => Foldable (EnvT e w) where
      foldMap :: (a -> m) -> EnvT e w a -> m
    foldMap f :: a -> m
    f (EnvT _ w :: w a
    w) = (a -> m) -> w a -> m
    forall (t :: * -> *) m a.
    (Foldable t, Monoid m) =>
    (a -> m) -> t a -> m
    foldMap a -> m
    f w a
    w

    instance Traversable w => Traversable (EnvT e w) where
      traverse :: (a -> f b) -> EnvT e w a -> f (EnvT e w b)
    traverse f :: a -> f b
    f (EnvT e :: e
    e w :: w a
    w) = e -> w b -> EnvT e w b
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT e
    e (w b -> EnvT e w b) -> f (w b) -> f (EnvT e w b)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (a -> f b) -> w a -> f (w b)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    traverse a -> f b
    f w a
    w

    -- | Retrieves the environment.
    ask :: EnvT e w a -> e
    ask :: EnvT e w a -> e
    ask (EnvT e :: e
    e _) = e
    e

    -- | Like 'ask', but modifies the resulting value with a function.
    --
    --   > asks = f . ask
    asks :: (e -> f) -> EnvT e w a -> f
    asks :: (e -> f) -> EnvT e w a -> f
    asks f :: e -> f
    f (EnvT e :: e
    e _) = e -> f
    f e
    e

    -- | Modifies the environment using the specified function.
    local :: (e -> e') -> EnvT e w a -> EnvT e' w a
    local :: (e -> e') -> EnvT e w a -> EnvT e' w a
    local f :: e -> e'
    f (EnvT e :: e
    e wa :: w a
    wa) = e' -> w a -> EnvT e' w a
    forall e (w :: * -> *) a. e -> w a -> EnvT e w a
    EnvT (e -> e'
    f e
    e) w a
    wa