    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE Rank2Types                 #-}

    -- | exports from "Yi.Config.Simple" which are useful to \"core yi\" rather than just config files.
    module Yi.Config.Simple.Types
     where

    import Lens.Micro.Platform (Lens')
    import Control.Monad.Base  (MonadBase)
    import Control.Monad.State (MonadState, StateT)
    import Yi.Config           (Config, configVariable)
    import Yi.Types            (YiConfigVariable)

    -- | The configuration monad. Run it with 'configMain'.
    newtype ConfigM a = ConfigM {
        forall a. ConfigM a -> StateT Config IO a
    runConfigM :: StateT Config IO a
      } deriving (Applicative ConfigM
    Applicative ConfigM =>
    (forall a b. ConfigM a -> (a -> ConfigM b) -> ConfigM b)
    -> (forall a b. ConfigM a -> ConfigM b -> ConfigM b)
    -> (forall a. a -> ConfigM a)
    -> Monad ConfigM
    forall a. a -> ConfigM a
    forall a b. ConfigM a -> ConfigM b -> ConfigM b
    forall a b. ConfigM a -> (a -> ConfigM b) -> ConfigM 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
    $c>>= :: forall a b. ConfigM a -> (a -> ConfigM b) -> ConfigM b
    >>= :: forall a b. ConfigM a -> (a -> ConfigM b) -> ConfigM b
    $c>> :: forall a b. ConfigM a -> ConfigM b -> ConfigM b
    >> :: forall a b. ConfigM a -> ConfigM b -> ConfigM b
    $creturn :: forall a. a -> ConfigM a
    return :: forall a. a -> ConfigM a
    Monad, (forall a b. (a -> b) -> ConfigM a -> ConfigM b)
    -> (forall a b. a -> ConfigM b -> ConfigM a) -> Functor ConfigM
    forall a b. a -> ConfigM b -> ConfigM a
    forall a b. (a -> b) -> ConfigM a -> ConfigM b
    forall (f :: * -> *).
    (forall a b. (a -> b) -> f a -> f b)
    -> (forall a b. a -> f b -> f a) -> Functor f
    $cfmap :: forall a b. (a -> b) -> ConfigM a -> ConfigM b
    fmap :: forall a b. (a -> b) -> ConfigM a -> ConfigM b
    $c<$ :: forall a b. a -> ConfigM b -> ConfigM a
    <$ :: forall a b. a -> ConfigM b -> ConfigM a
    Functor, Functor ConfigM
    Functor ConfigM =>
    (forall a. a -> ConfigM a)
    -> (forall a b. ConfigM (a -> b) -> ConfigM a -> ConfigM b)
    -> (forall a b c.
        (a -> b -> c) -> ConfigM a -> ConfigM b -> ConfigM c)
    -> (forall a b. ConfigM a -> ConfigM b -> ConfigM b)
    -> (forall a b. ConfigM a -> ConfigM b -> ConfigM a)
    -> Applicative ConfigM
    forall a. a -> ConfigM a
    forall a b. ConfigM a -> ConfigM b -> ConfigM a
    forall a b. ConfigM a -> ConfigM b -> ConfigM b
    forall a b. ConfigM (a -> b) -> ConfigM a -> ConfigM b
    forall a b c. (a -> b -> c) -> ConfigM a -> ConfigM b -> ConfigM 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
    $cpure :: forall a. a -> ConfigM a
    pure :: forall a. a -> ConfigM a
    $c<*> :: forall a b. ConfigM (a -> b) -> ConfigM a -> ConfigM b
    <*> :: forall a b. ConfigM (a -> b) -> ConfigM a -> ConfigM b
    $cliftA2 :: forall a b c. (a -> b -> c) -> ConfigM a -> ConfigM b -> ConfigM c
    liftA2 :: forall a b c. (a -> b -> c) -> ConfigM a -> ConfigM b -> ConfigM c
    $c*> :: forall a b. ConfigM a -> ConfigM b -> ConfigM b
    *> :: forall a b. ConfigM a -> ConfigM b -> ConfigM b
    $c<* :: forall a b. ConfigM a -> ConfigM b -> ConfigM a
    <* :: forall a b. ConfigM a -> ConfigM b -> ConfigM a
    Applicative, MonadState Config, MonadBase IO)

    -- | Fields that can be modified with all lens machinery.
    type Field a = Lens' Config a

    {- | Accessor for any 'YiConfigVariable', to be used by modules defining
    'YiConfigVariable's. Such modules should provide a custom-named field.
    For instance, take the following hypothetical 'YiConfigVariable':

    @newtype UserName = UserName { unUserName :: String }
      deriving(Typeable, Binary, Default)
    instance YiConfigVariable UserName

    $(nameDeriveAccessors ''UserName (\n -> Just (n ++ \"A\")))

    userName :: 'Field' 'String'
    userName = unUserNameA '.' 'customVariable'@

    Here, the hypothetical library would provide the field @userName@ to be used in preference to @customVariable@.
    -}
    customVariable :: YiConfigVariable a => Field a
    customVariable :: forall a. YiConfigVariable a => Field a
    customVariable = (a -> f a) -> Config -> f Config
    forall a. YiConfigVariable a => Field a
    Lens Config Config a a
    configVariable