mirror of
https://github.com/polysemy-research/polysemy.git
synced 2024-12-12 02:13:15 +03:00
more combinators
This commit is contained in:
parent
0b998cf6f9
commit
537b3cbaad
@ -4,7 +4,7 @@
|
||||
{-# LANGUAGE RankNTypes #-}
|
||||
{-# LANGUAGE TypeOperators #-}
|
||||
|
||||
module Eff.Combinators where
|
||||
module Eff.Interpretation where
|
||||
|
||||
import qualified Control.Monad.Trans.Except as E
|
||||
import Control.Monad.Trans.Cont
|
||||
@ -35,12 +35,12 @@ interpret f (Freer m) = Freer $ \k -> m $ \u ->
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- | Like 'interpret', but with access to intermediate state.
|
||||
interpretS
|
||||
stateful
|
||||
:: (eff ~> S.StateT s (Eff r))
|
||||
-> s
|
||||
-> Eff (eff ': r) ~> Eff r
|
||||
interpretS f s = transform (flip S.evalStateT s) f
|
||||
{-# INLINE interpretS #-}
|
||||
stateful f s = transform (flip S.evalStateT s) f
|
||||
{-# INLINE stateful #-}
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@ -48,8 +48,8 @@ interpretS f s = transform (flip S.evalStateT s) f
|
||||
-- useful for interpreters which would like to introduce some intermediate
|
||||
-- effects before immediately handling them.
|
||||
replace
|
||||
:: (eff ~> eff')
|
||||
-> Eff (eff ': r) ~> Eff (eff' ': r)
|
||||
:: (eff1 ~> eff2)
|
||||
-> Eff (eff1 ': r) ~> Eff (eff2 ': r)
|
||||
replace = naturally weaken
|
||||
{-# INLINE replace #-}
|
||||
|
||||
@ -80,6 +80,20 @@ shortCircuit
|
||||
-> Eff (eff ': r) a
|
||||
-> Eff r (Either e a)
|
||||
shortCircuit f = transform E.runExceptT $ \e -> f e
|
||||
{-# INLINE shortCircuit #-}
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- | Intercept an effect without removing it from the effect stack.
|
||||
intercept
|
||||
:: Member eff r
|
||||
=> (eff ~> Eff r)
|
||||
-> Eff r ~> Eff r
|
||||
intercept f (Freer m) = Freer $ \k -> m $ \u ->
|
||||
case prj u of
|
||||
Nothing -> k u
|
||||
Just e -> runIt k $ f e
|
||||
{-# INLINE intercept #-}
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@ -116,13 +130,6 @@ naturally z f (Freer m) = Freer $ \k -> m $ \u ->
|
||||
{-# INLINE naturally #-}
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- | Analogous to MTL's 'lift'.
|
||||
raise :: Eff r a -> Eff (u ': r) a
|
||||
raise = hoistEff weaken
|
||||
{-# INLINE raise #-}
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- | Introduce a new effect directly underneath the top of the stack. This is
|
||||
-- often useful for interpreters which would like to introduce some intermediate
|
@ -58,6 +58,7 @@ liftEff :: f x -> Freer f x
|
||||
liftEff u = Freer $ \k -> k u
|
||||
{-# INLINE liftEff #-}
|
||||
|
||||
|
||||
type f ~> g = forall x. f x -> g x
|
||||
infixr 1 ~>
|
||||
|
||||
@ -68,7 +69,7 @@ send t = Freer $ \k -> k $ inj t
|
||||
|
||||
|
||||
runM :: Monad m => Freer (Union '[m]) a -> m a
|
||||
runM z = runFreer z extract
|
||||
runM = runIt extract
|
||||
{-# INLINE runM #-}
|
||||
|
||||
|
||||
@ -79,3 +80,10 @@ run = runIdentity . runM
|
||||
|
||||
runIt :: Monad m => (forall t. f t -> m t) -> Freer f a -> m a
|
||||
runIt k m = runFreer m k
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- | Analogous to MTL's 'lift'.
|
||||
raise :: Eff r a -> Eff (u ': r) a
|
||||
raise = hoistEff weaken
|
||||
{-# INLINE raise #-}
|
||||
|
||||
|
20
src/Lib.hs
20
src/Lib.hs
@ -12,7 +12,7 @@ module Lib where
|
||||
import qualified Control.Monad.Trans.Except as E
|
||||
import qualified Control.Monad.Trans.State.Strict as S
|
||||
import Data.OpenUnion
|
||||
import Eff.Combinators
|
||||
import Eff.Interpretation
|
||||
import Eff.Type
|
||||
|
||||
|
||||
@ -39,20 +39,18 @@ foom = do
|
||||
get @String
|
||||
|
||||
|
||||
runTeletype :: forall r a. Member IO r => Eff (State String ': r) a -> Eff r a
|
||||
runTeletype = interpret bind
|
||||
where
|
||||
bind :: forall x. State String x -> Eff r x
|
||||
bind Get = send getLine
|
||||
bind (Put s) = send $ putStrLn s
|
||||
runTeletype :: Member IO r => Eff (State String ': r) a -> Eff r a
|
||||
runTeletype = interpret $ \case
|
||||
Get -> send getLine
|
||||
Put s -> send $ putStrLn s
|
||||
|
||||
|
||||
-- main :: IO ()
|
||||
-- main = runM (runState "fuck" foom) >>= print
|
||||
|
||||
|
||||
runState :: forall s r a. s -> Eff (State s ': r) a -> Eff r a
|
||||
runState = interpretS $ \case
|
||||
runState :: s -> Eff (State s ': r) a -> Eff r a
|
||||
runState = stateful $ \case
|
||||
Get -> S.get
|
||||
Put s' -> S.put s'
|
||||
|
||||
@ -73,3 +71,7 @@ runError = shortCircuit $ \(Error e) -> E.throwE e
|
||||
runErrorRelay :: Eff (Error e ': r) a -> Eff r (Either e a)
|
||||
runErrorRelay = relay (pure . Right) $ \(Error e) _ -> pure $ Left e
|
||||
|
||||
|
||||
subsume :: Member eff r => Eff (eff ': r) ~> Eff r
|
||||
subsume = interpret send
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user