{-# LANGUAGE DeriveFunctor, ExistentialQuantification, FlexibleContexts, FlexibleInstances, LambdaCase, MultiParamTypeClasses, StandaloneDeriving, TypeOperators, UndecidableInstances #-}
module Control.Effect.Reader
( Reader(..)
, ask
, asks
, local
, runReader
, ReaderC(..)
) where
import Control.Effect.Carrier
import Control.Effect.Sum
import Control.Effect.Internal
data Reader r m k
= Ask (r -> k)
| forall b . Local (r -> r) (m b) (b -> k)
deriving instance Functor (Reader r m)
instance HFunctor (Reader r) where
hmap _ (Ask k) = Ask k
hmap f (Local g m k) = Local g (f m) k
instance Effect (Reader r) where
handle state handler (Ask k) = Ask (handler . (<$ state) . k)
handle state handler (Local f m k) = Local f (handler (m <$ state)) (handler . fmap k)
ask :: (Member (Reader r) sig, Carrier sig m) => m r
ask = send (Ask ret)
asks :: (Member (Reader r) sig, Carrier sig m) => (r -> a) -> m a
asks f = send (Ask (ret . f))
local :: (Member (Reader r) sig, Carrier sig m) => (r -> r) -> m a -> m a
local f m = send (Local f m ret)
runReader :: forall r sig m a . (Carrier sig m, Monad m) => r -> Eff (ReaderC r m) a -> m a
runReader r m = runReaderC (interpret m) r
newtype ReaderC r m a = ReaderC { runReaderC :: r -> m a }
instance (Carrier sig m, Monad m) => Carrier (Reader r :+: sig) (ReaderC r m) where
ret a = ReaderC (const (ret a))
eff op = ReaderC (\ r -> handleSum (eff . handleReader r runReaderC) (\case
Ask k -> runReaderC (k r) r
Local f m k -> runReaderC m (f r) >>= flip runReaderC r . k) op)