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