{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE Trustworthy #-}
module Control.Eff.State.OnDemand where
import Control.Eff.Internal
import Control.Eff.Writer.Lazy
import Control.Eff.Reader.Lazy
import Data.OpenUnion
import Control.Monad.Base
import Control.Monad.Trans.Control
data OnDemandState s v where
Get :: OnDemandState s s
Put :: s -> OnDemandState s ()
Delay :: Eff '[OnDemandState s] a -> OnDemandState s a
instance ( MonadBase m m
, SetMember Lift (Lift m) r
, MonadBaseControl m (Eff r)
) => MonadBaseControl m (Eff (OnDemandState s ': r)) where
type StM (Eff (OnDemandState s ': r)) a = StM (Eff r) (a,s)
liftBaseWith f = do s <- get
raise $ liftBaseWith $ \runInBase ->
f (runInBase . runState s)
restoreM x = do (a, s :: s) <- raise (restoreM x)
put s
return a
{-# NOINLINE get #-}
get :: Member (OnDemandState s) r => Eff r s
get = send Get
{-# RULES
"get/bind" forall k. get >>= k = send Get >>= k
#-}
{-# NOINLINE put #-}
put :: Member (OnDemandState s) r => s -> Eff r ()
put s = send (Put s)
{-# RULES
"put/bind" forall k v. put v >>= k = send (Put v) >>= k
#-}
{-# RULES
"put/semibind" forall k v. put v >> k = send (Put v) >>= (\() -> k)
#-}
onDemand :: Member (OnDemandState s) r => Eff '[OnDemandState s] v -> Eff r v
onDemand = send . Delay
runState' :: s -> Eff (OnDemandState s ': r) w -> Eff r (w,s)
runState' s =
handle_relay_s s
(\s0 x -> return (x,s0))
(\s0 sreq k -> case sreq of
Get -> k s0 s0
Put s1 -> k s1 ()
Delay m1 -> let ~(x,s1) = run $ runState' s0 m1
in k s1 x)
runState :: s
-> Eff (OnDemandState s ': r) w
-> Eff r (w,s)
runState s (Val x) = return (x,s)
runState s0 (E u0 q) = case decomp u0 of
Right Get -> runState s0 (q ^$ s0)
Right (Put s1) -> runState s1 (q ^$ ())
Right (Delay m1) -> let ~(x,s1) = run $ runState s0 m1
in runState s1 (q ^$ x)
Left u -> E u (singleK (\x -> runState s0 (q ^$ x)))
modify :: (Member (OnDemandState s) r) => (s -> s) -> Eff r ()
modify f = get >>= put . f
evalState :: s -> Eff (OnDemandState s ': r) w -> Eff r w
evalState s = fmap fst . runState s
execState :: s -> Eff (OnDemandState s ': r) w -> Eff r s
execState s = fmap snd . runState s
runStateR :: s -> Eff (Writer s ': Reader s ': r) w -> Eff r (w,s)
runStateR s0 m0 = loop s0 m0
where
loop :: s -> Eff (Writer s ': Reader s ': r) w -> Eff r (w,s)
loop s (Val x) = return (x,s)
loop s (E u0 q) = case decomp u0 of
Right (Tell w) -> k w ()
Left u -> case decomp u of
Right Ask -> k s s
Left u1 -> E u1 (singleK (k s))
where k x = qComp q (loop x)
runStateBack0 :: Eff '[OnDemandState s] a -> (a,s)
runStateBack0 m =
let (x,s) = go s m in
(x,s)
where
go :: s -> Eff '[OnDemandState s] a -> (a,s)
go s (Val x) = (x,s)
go s0 (E u q) = case decomp u of
Right Get -> go s0 $ (q ^$ s0)
Right (Put s1) -> let ~(x,sp) = go sp $ (q ^$ ()) in (x,s1)
Right (Delay m1) -> let ~(x,s1) = go s0 m1 in go s1 $ (q ^$ x)
Left _ -> error "Impossible happened: Union []"
runStateBack :: Eff '[OnDemandState s] a -> (a,s)
runStateBack m =
let (x,(_sg,sp)) = run $ go (sp,[]) m in
(x,head sp)
where
go :: ([s],[s]) -> Eff '[OnDemandState s] a -> Eff '[] (a,([s],[s]))
go ss = handle_relay_s ss (\ss0 x -> return (x,ss0))
(\ss0@(sg,sp) req k -> case req of
Get -> k ss0 (head sg)
Put s1 -> k (tail sg,sp++[s1]) ()
Delay m1 -> let ~(x,ss1) = run $ go ss0 m1
in k ss1 x)