{-# LANGUAGE ScopedTypeVariables, TypeFamilies, FlexibleContexts #-}

{-# LANGUAGE DataKinds, GADTs #-}

{-# LANGUAGE DeriveGeneric #-}

-- | The regular old 'MonadReader' effect with some differences. First, there's no functional

--   dependency limiting your stack to a single environment type. This means less type inference so

--   it might not be enough to just write 'readEnv'. Write 'readEnv @MyEnvType' instead using

--   TypeApplications.

--

--   Second, the function has a less generic name and is called 'readEnv'.

--

--   Third, since it's a part of this effect framework, you get a 'implementReadEnv' function with

--   which you can provide a different environment implementation _at runtime_.

module Control.Effects.Reader (module Control.Effects.Reader, module Control.Effects) where



import Control.Effects

import GHC.Generics



newtype ReadEnv e m = ReadEnvMethods

    { _readEnv :: m e }

    deriving (Generic)

instance Effect (ReadEnv e)



-- | Read a value of type 'e'. Use with the TypeApplications extension to

--   help with type inference

--   @readEnv \@Int@

readEnv :: forall e m. MonadEffect (ReadEnv e) m => m e

readEnv = _readEnv effect



-- | Use the given action in the underlying monad to provide environment

--   values. You can think of @implementReadEnv x m@ as replacing all 'readEnv' calls

--   in 'm' with 'x'.

implementReadEnv :: Functor m => m e -> RuntimeImplemented (ReadEnv e) m a -> m a

implementReadEnv m = implement (ReadEnvMethods m)