mirror of
https://github.com/polysemy-research/polysemy.git
synced 2024-12-02 02:43:39 +03:00
Document change in semantics based on order of interpreters (#181)
* Polysemy.Internal: document change in semantics based on order of interpreters * Polysemy.Internal: use new 'evalState' instead of mapping 'runState' in example * Polysemy.Internal, DoctestSpec: properly support doctest * Polysemy.Internal: small corrections
This commit is contained in:
parent
c53357ca92
commit
d803c81054
@ -40,6 +40,11 @@ import Polysemy.Internal.PluginLookup
|
||||
import Polysemy.Internal.Union
|
||||
|
||||
|
||||
-- $setup
|
||||
-- >>> import Data.Function
|
||||
-- >>> import Polysemy.State
|
||||
-- >>> import Polysemy.Error
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
-- | The 'Sem' monad handles computations of arbitrary extensible effects.
|
||||
-- A value of type @Sem r@ describes a program with the capabilities of
|
||||
@ -72,6 +77,53 @@ import Polysemy.Internal.Union
|
||||
-- is the order in which you call the interpreters that determines the
|
||||
-- monomorphic representation of the @r@ parameter.
|
||||
--
|
||||
-- Order of interpreters can be important - it determines behaviour of effects
|
||||
-- that manipulate state or change control flow. For example, when
|
||||
-- interpreting this action:
|
||||
--
|
||||
-- >>> :{
|
||||
-- example :: Members '[State String, Error String] r => Sem r String
|
||||
-- example = do
|
||||
-- put "start"
|
||||
-- let throwing, catching :: Members '[State String, Error String] r => Sem r String
|
||||
-- throwing = do
|
||||
-- modify (++"-throw")
|
||||
-- throw "error"
|
||||
-- get
|
||||
-- catching = do
|
||||
-- modify (++"-catch")
|
||||
-- get
|
||||
-- catch @String throwing (\ _ -> catching)
|
||||
-- :}
|
||||
--
|
||||
-- when handling 'Polysemy.Error.Error' first, state is preserved after error
|
||||
-- occurs:
|
||||
--
|
||||
-- >>> :{
|
||||
-- example
|
||||
-- & runError
|
||||
-- & fmap (either id id)
|
||||
-- & evalState ""
|
||||
-- & runM
|
||||
-- & (print =<<)
|
||||
-- :}
|
||||
-- "start-throw-catch"
|
||||
--
|
||||
-- while handling 'Polysemy.State.State' first discards state in such cases:
|
||||
--
|
||||
-- >>> :{
|
||||
-- example
|
||||
-- & evalState ""
|
||||
-- & runError
|
||||
-- & fmap (either id id)
|
||||
-- & runM
|
||||
-- & (print =<<)
|
||||
-- :}
|
||||
-- "start-catch"
|
||||
--
|
||||
-- A good rule of thumb is to handle effects which should have \"global\"
|
||||
-- behaviour over other effects later in the chain.
|
||||
--
|
||||
-- After all of your effects are handled, you'll be left with either
|
||||
-- a @'Sem' '[] a@ or a @'Sem' '[ 'Embed' m ] a@ value, which can be
|
||||
-- consumed respectively by 'run' and 'runM'.
|
||||
|
@ -23,6 +23,8 @@ spec = parallel $ describe "Error messages" $ it "should pass the doctest" $ doc
|
||||
, "-XTypeOperators"
|
||||
, "-XUnicodeSyntax"
|
||||
|
||||
, "-package type-errors"
|
||||
|
||||
#if __GLASGOW_HASKELL__ < 806
|
||||
, "-XMonadFailDesugaring"
|
||||
, "-XTypeInType"
|
||||
@ -32,6 +34,7 @@ spec = parallel $ describe "Error messages" $ it "should pass the doctest" $ doc
|
||||
|
||||
-- Modules that are explicitly imported for this test must be listed here
|
||||
, "src/Polysemy.hs"
|
||||
, "src/Polysemy/Error.hs"
|
||||
, "src/Polysemy/Output.hs"
|
||||
, "src/Polysemy/Reader.hs"
|
||||
, "src/Polysemy/Resource.hs"
|
||||
|
Loading…
Reference in New Issue
Block a user