{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE Safe #-}
module Control.Eff.Reader.Strict ( Reader (..)
, withReader
, ask
, local
, reader
, runReader
) where
import Control.Eff
import Control.Eff.Extend
import Control.Monad.Base
import Control.Monad.Trans.Control
import Data.Function (fix)
data Reader e v where
Ask :: Reader e e
withReader :: Monad m => a -> e -> m a
withReader x _ = return x
instance Handle (Reader e) r a (e -> k) where
handle step q Ask e = step (q ^$ e) e
ask :: (Member (Reader e) r) => Eff r e
ask = send Ask
runReader :: e -> Eff (Reader e ': r) w -> Eff r w
runReader !e m = fix (handle_relay withReader) m e
local :: forall e a r. Member (Reader e) r =>
(e -> e) -> Eff r a -> Eff r a
local f m = do
e <- reader f
(fix (respond_relay @(Reader e) withReader)) m e
reader :: (Member (Reader e) r) => (e -> a) -> Eff r a
reader f = f `fmap` ask
instance ( MonadBase m m
, LiftedBase m s
) => MonadBaseControl m (Eff (Reader e ': s)) where
type StM (Eff (Reader e ': s)) a = StM (Eff s) a
liftBaseWith f = do !e <- ask
raise $ liftBaseWith $ \runInBase ->
f (runInBase . runReader e)
restoreM = raise . restoreM