cleff-0.3.1.0: src/Cleff/Reader.hs
{-# LANGUAGE Trustworthy #-}
-- |
-- Copyright: (c) 2021 Xy Ren
-- License: BSD3
-- Maintainer: xy.r@outlook.com
-- Stability: experimental
-- Portability: non-portable (GHC only)
module Cleff.Reader
( -- * Effect
Reader (..)
-- * Operations
, ask
, local
, asks
-- * Interpretations
, runReader
, magnify
) where
import Cleff
import Lens.Micro (Lens', (%~), (&), (^.))
-- * Effect
-- | An effect capable of providing an immutable environment @r@ that can be read. This roughly corresponds to the
-- @MonadReader@ typeclass and @ReaderT@ monad transformer in the @mtl@ library.
data Reader r :: Effect where
Ask :: Reader r m r
Local :: (r -> r) -> m a -> Reader r m a
-- * Operations
makeEffect_ ''Reader
-- | Obtain the environment value.
ask :: Reader r :> es => Eff es r
-- | Modify the environment value temporarily for a computation.
local :: Reader r :> es
=> (r -> r) -- ^ The function that modifies the environment
-> Eff es a -- ^ The computation to run with the modified environment
-> Eff es a
-- | Apply a function to the result of 'ask'.
asks :: Reader r :> es => (r -> s) -> Eff es s
asks = (<$> ask)
-- * Interpretations
-- | Run a 'Reader' effect with a given environment value.
runReader :: r -> Eff (Reader r : es) ~> Eff es
runReader x = interpret (h x)
where
h :: r -> Handler (Reader r) es
h r = \case
Ask -> pure r
Local f m -> toEffWith (h (f r)) m
{-# INLINE runReader #-}
-- | Run a 'Reader' effect in terms of a larger 'Reader' via a 'Lens''.
magnify :: Reader t :> es => Lens' t r -> Eff (Reader r : es) ~> Eff es
magnify field = interpret \case
Ask -> asks (^. field)
Local f m -> local (& field %~ f) $ toEff m
{-# INLINE magnify #-}