{-# 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@ approach. data Reader r :: Effect where Ask :: Reader r m r Local :: (r -> r) -> m a -> Reader r m a -- * Operations makeEffect ''Reader -- | Apply a function on 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 #-}