{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE QuantifiedConstraints #-}
module Polysemy.Interpretation
(
makeSemantic
, makeSemantic_
, interpret
, intercept
, reinterpret
, reinterpret2
, interpretH
, interceptH
, reinterpretH
, reinterpret2H
, stateful
, lazilyStateful
, raise
, inlineRecursiveCalls
, Tactical
, pureT
, runT
, bindT
) where
import qualified Control.Monad.Trans.State.Lazy as LS
import qualified Control.Monad.Trans.State.Strict as S
import Polysemy.Internal
import Polysemy.Internal.CustomErrors
import Polysemy.Internal.Effect
import Polysemy.Internal.TH.Effect
import Polysemy.Internal.TH.Performance
import Polysemy.Internal.Tactics
import Polysemy.Internal.Union
swap :: (a, b) -> (b, a)
swap ~(a, b) = (b, a)
interpret
:: FirstOrder e "interpret"
=> (∀ x m. e m x -> Semantic r x)
-> Semantic (e ': r) a
-> Semantic r a
interpret f = interpretH $ \(e :: e m x) -> liftT @m $ f e
interpretH
:: forall e r a
. (∀ x m . e m x -> Tactical e m r x)
-> Semantic (e ': r) a
-> Semantic r a
interpretH f (Semantic m) = m $ \u ->
case decomp u of
Left x -> liftSemantic $ hoist (interpretH_b f) x
Right (Yo e s d y) -> do
a <- runTactics s (raise . interpretH_b f . d) (f e)
pure $ y a
{-# INLINE interpretH #-}
interpretInStateT
:: (∀ x m. e m x -> S.StateT s (Semantic r) x)
-> s
-> Semantic (e ': r) a
-> Semantic r (s, a)
interpretInStateT f s (Semantic m) = Semantic $ \k ->
fmap swap $ flip S.runStateT s $ m $ \u ->
case decomp u of
Left x -> S.StateT $ \s' ->
k . fmap swap
. weave (s', ()) (uncurry $ interpretInStateT_b f)
$ x
Right (Yo e z _ y) ->
fmap (y . (<$ z)) $ S.mapStateT (usingSemantic k) $ f e
{-# INLINE interpretInStateT #-}
interpretInLazyStateT
:: (∀ x m. e m x -> LS.StateT s (Semantic r) x)
-> s
-> Semantic (e ': r) a
-> Semantic r (s, a)
interpretInLazyStateT f s (Semantic m) = Semantic $ \k ->
fmap swap $ flip LS.runStateT s $ m $ \u ->
case decomp u of
Left x -> LS.StateT $ \s' ->
k . fmap swap
. weave (s', ()) (uncurry $ interpretInLazyStateT_b f)
$ x
Right (Yo e z _ y) ->
fmap (y . (<$ z)) $ LS.mapStateT (usingSemantic k) $ f e
{-# INLINE interpretInLazyStateT #-}
stateful
:: (∀ x m. e m x -> s -> Semantic r (s, x))
-> s
-> Semantic (e ': r) a
-> Semantic r (s, a)
stateful f = interpretInStateT $ \e -> S.StateT $ fmap swap . f e
{-# INLINE[3] stateful #-}
lazilyStateful
:: (∀ x m. e m x -> s -> Semantic r (s, x))
-> s
-> Semantic (e ': r) a
-> Semantic r (s, a)
lazilyStateful f = interpretInLazyStateT $ \e -> LS.StateT $ fmap swap . f e
{-# INLINE[3] lazilyStateful #-}
reinterpretH
:: forall e2 e1 r a
. (∀ m x. e1 m x -> Tactical e1 m (e2 ': r) x)
-> Semantic (e1 ': r) a
-> Semantic (e2 ': r) a
reinterpretH f (Semantic m) = Semantic $ \k -> m $ \u ->
case decompCoerce u of
Left x -> k $ hoist (reinterpretH_b f) $ x
Right (Yo e s d y) -> do
a <- usingSemantic k $ runTactics s (raise . reinterpretH_b f . d) $ f e
pure $ y a
{-# INLINE[3] reinterpretH #-}
reinterpret
:: forall e2 e1 r a
. FirstOrder e1 "reinterpret"
=> (∀ m x. e1 m x -> Semantic (e2 ': r) x)
-> Semantic (e1 ': r) a
-> Semantic (e2 ': r) a
reinterpret f = reinterpretH $ \(e :: e m x) -> liftT @m $ f e
{-# INLINE[3] reinterpret #-}
reinterpret2H
:: forall e2 e3 e1 r a
. (∀ m x. e1 m x -> Tactical e1 m (e2 ': e3 ': r) x)
-> Semantic (e1 ': r) a
-> Semantic (e2 ': e3 ': r) a
reinterpret2H f (Semantic m) = Semantic $ \k -> m $ \u ->
case decompCoerce u of
Left x -> k $ weaken $ hoist (reinterpret2H_b f) $ x
Right (Yo e s d y) -> do
a <- usingSemantic k $ runTactics s (raise . reinterpret2H_b f . d) $ f e
pure $ y a
{-# INLINE[3] reinterpret2H #-}
reinterpret2
:: forall e2 e3 e1 r a
. FirstOrder e1 "reinterpret2"
=> (∀ m x. e1 m x -> Semantic (e2 ': e3 ': r) x)
-> Semantic (e1 ': r) a
-> Semantic (e2 ': e3 ': r) a
reinterpret2 f = reinterpret2H $ \(e :: e m x) -> liftT @m $ f e
{-# INLINE[3] reinterpret2 #-}
intercept
:: forall e r a
. ( Member e r
, FirstOrder e "intercept"
)
=> (∀ x m. e m x -> Semantic r x)
-> Semantic r a
-> Semantic r a
intercept f = interceptH $ \(e :: e m x) -> liftT @m $ f e
{-# INLINE intercept #-}
interceptH
:: forall e r a. Member e r
=> (∀ x m. e m x -> Tactical e m r x)
-> Semantic r a
-> Semantic r a
interceptH f (Semantic m) = Semantic $ \k -> m $ \u ->
case prj @e u of
Just (Yo e s d y) ->
usingSemantic k $ fmap y $ runTactics s (raise . d) $ f e
Nothing -> k u
{-# INLINE interceptH #-}
interpretH_b
:: forall e r a
. (∀ x m . e m x -> Tactical e m r x)
-> Semantic (e ': r) a
-> Semantic r a
interpretH_b = interpretH
{-# NOINLINE interpretH_b #-}
interpretInStateT_b
:: (∀ x m. e m x -> S.StateT s (Semantic r) x)
-> s
-> Semantic (e ': r) a
-> Semantic r (s, a)
interpretInStateT_b = interpretInStateT
{-# NOINLINE interpretInStateT_b #-}
interpretInLazyStateT_b
:: (∀ x m. e m x -> LS.StateT s (Semantic r) x)
-> s
-> Semantic (e ': r) a
-> Semantic r (s, a)
interpretInLazyStateT_b = interpretInLazyStateT
{-# NOINLINE interpretInLazyStateT_b #-}
reinterpretH_b
:: forall e2 e1 r a
. (∀ m x. e1 m x -> Tactical e1 m (e2 ': r) x)
-> Semantic (e1 ': r) a
-> Semantic (e2 ': r) a
reinterpretH_b = reinterpretH
{-# NOINLINE reinterpretH_b #-}
reinterpret2H_b
:: forall e2 e3 e1 r a
. (∀ m x. e1 m x -> Tactical e1 m (e2 ': e3 ': r) x)
-> Semantic (e1 ': r) a
-> Semantic (e2 ': e3 ': r) a
reinterpret2H_b = reinterpret2H
{-# NOINLINE reinterpret2H_b #-}