packages feed

bluefin 0.0.17.1 → 0.7.0.0

raw patch · 37 files changed

Files

CHANGELOG.md view
@@ -1,3 +1,110 @@+# 0.7.0.0++* Fix `Reader` bug that caused incorrect scoping in+  `awaitYield`/`connectRequests`/`streamConsume`/`connectCoroutines`++  <https://github.com/tomjaguarpaw/bluefin/issues/98>++# 0.6.0.0++* Changed type of `runEff` to match `runEff_`++# 0.5.100.0++* Covert to "capability" nomenclature++  See module "Bluefin.Capability" for a guide to the new naming. Users+  should convert to the new modules, since the old ones will be+  deprecated in the future. This is indicated by a comment in the+  documentation for each module that will undergo deprecation.++  * Add new "Capability" modules++  * Use "capability" terminology throughout documentation++# 0.5.1.0++* Add `<:` type synonym for `:>`++  It is suggested you switch your uses of `:>` to `<:` because it is a+  "subset" like constraint and the latter looks more like a subset+  symbol.  The former may be deprecated and then removed in future+  versions.++# 0.5.0.0++* Fix dodgy `Bluefin.Primitive.primitive` implementation++# 0.4.3.0++* Add `Bluefin.GadtEffect`++* Add `Bluefin.HandleReader.asksHandle`++* Restrict type parameter of `PrimStateEff` to `Effects`++  This is technically a breaking change, but we did not enforce a+  major version bump for it.++# 0.4.2.0++* Add `Bluefin.DslBuilderEff`++* Add `Bluefin.Prim`++# 0.4.1.0++* Depend on `bluefin-internal >= 0.4.1.0` to pick up `MonadFix`+  instance for `Eff`++# 0.4.0.1++* Documentation only++# 0.4.0.0++* Move `mapHandle` out of class `Handle` and remove `handleMapHandle`.+  See `Bluefin.Compound` for instructions about migrating.++# 0.2.7.0++* Add `Bluefin.Compound.handleOneWayCoercible`++* Add `Bluefin.Compound.oneWayCoercibleTrustMe`++* Add `OneWayCoercible` instances for Generic types++# 0.2.6.0++* Add `Bluefin.Exception.GeneralBracket`, thanks to Shea Levy++# 0.2.5.0++* Add `finally`++# 0.2.4.0++* Add `Bluefin.CloneHandle` and `Bluefin.IO.withEffToIOCloneHandle`++# 0.2.3.0++* Add `Bluefin.DslBuilder`++## 0.2.2.0++* `Bluefin.Compound`: add `OneWayCoercible`, `OneWayCoercibleHandle`,+  `gOneWayCoercible` and re-export `Generic`++## 0.2.1.0++* `Bluefin.Compound`: Add `handleImpl`, `HandleD` and+  `handleMapHandle`++## 0.2.0.0++* Transitive version bump because of choice of different incoherent+  instance for `:>` for better type inference.+ ## 0.0.17.1  * Documentation only, thanks to @ShilohAlleyne
bluefin.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               bluefin-version:            0.0.17.1+version:            0.7.0.0 license:            MIT license-file:       LICENSE author:             Tom Ellis@@ -21,17 +21,34 @@       NoImplicitPrelude     exposed-modules:       Bluefin,+      Bluefin.Capability,+      Bluefin.Capability.Ask,+      Bluefin.Capability.AskCapability,+      Bluefin.Capability.Await,+      Bluefin.Capability.JumpTo,+      Bluefin.Capability.Modify,+      Bluefin.Capability.Request,+      Bluefin.Capability.ReturnEarly,+      Bluefin.Capability.Tell,+      Bluefin.Capability.Throw,+      Bluefin.Capability.Yield,       Bluefin.Compound,       Bluefin.Consume,       Bluefin.Coroutine,+      Bluefin.CloneableHandle,+      Bluefin.DslBuilder,+      Bluefin.DslBuilderEff,       Bluefin.EarlyReturn,       Bluefin.Eff,       Bluefin.Exception,+      Bluefin.Exception.GeneralBracket,+      Bluefin.GadtEffect,       Bluefin.HandleReader,       Bluefin.IO,       Bluefin.Jump,       Bluefin.Pipes,       Bluefin.Pipes.Prelude,+      Bluefin.Prim,       Bluefin.Reader,       Bluefin.State,       Bluefin.StateSource,@@ -39,6 +56,6 @@       Bluefin.System.IO,       Bluefin.Writer,     build-depends:-      bluefin-internal >= 0.1.1.0 && < 0.2+      bluefin-internal >= 0.7 && < 0.8     hs-source-dirs:   src     default-language: Haskell2010
src/Bluefin.hs view
@@ -4,16 +4,16 @@     -- | Bluefin is an effect system which allows you to freely mix a     -- variety of effects, including     ---    --  * "Bluefin.EarlyReturn", for early return-    --  * "Bluefin.Exception", for exceptions+    --  * "Bluefin.Capability.ReturnEarly", for early return+    --  * "Bluefin.Capability.Throw", for exceptions     --  * "Bluefin.IO", for I/O-    --  * "Bluefin.State", for mutable state-    --  * "Bluefin.Stream", for streams+    --  * "Bluefin.Capability.Modify", for mutable state+    --  * "Bluefin.Capability.Yield", for streams     --     -- and to create your own effects in terms of existing ones     -- ("Bluefin.Compound").     -- Bluefin effects are accessed explicitly through-    -- value-level handles.+    -- value-level capabilities.      -- * Why even use an effect system? @@ -107,17 +107,18 @@     -- question: if @let@ bindings don't interact with effects,     -- because we can inline them freely, then how /can/ we perform     -- effects in Haskell, and maintain control over the order in-    -- which various operations occur?  For a hour-long answer,+    -- which various operations occur?  For an hour-long answer,     -- concluding with an explanation of the development of effect     -- systems, you can watch "[A History of Effect-    -- systems](https://www.youtube.com/watch?v=RsTuy1jXQ6Y)" by Tom+    -- systems](https://www.youtube.com/watch?v=RsTuy1jXQ6Y)" by Bluefin author Tom     -- Ellis (recorded at Zurihac 2025).     ---    -- The short answer is: 'Control.Monad.Monad's.  @Monad@ is a+    -- The short answer is: t'Control.Monad.Monad's.  @Monad@ is a     -- general interface that permits ordering of operations.     -- Instances of @Monad@ from early in the development of Haskell-    -- include 'Prelude.IO', 'Control.Monad.Trans.State.State',-    -- 'Prelude.Either' and 'Control.Monad.Trans.State.Writer', all of+    -- include t'Prelude.IO',+    -- t'Control.Monad.Trans.State.Strict.State', t'Prelude.Either'+    -- and t'Control.Monad.Trans.Writer.CPS.Writer', all of     -- which are still in use today.  For example, to manipulate     -- mutable state we can't use @let@ bindings in the following way:     --@@ -139,7 +140,9 @@     --     -- which is not what we want at all: the final value would just be     -- @"Initial value"@. An approach that /does/ work is to simulate-    -- mutable state using an ad hoc "state passing" pattern:+    -- mutable state using an ad hoc "state passing" pattern.  Here+    -- the variables @s1@ and @s2@ represent different values of the+    -- same state at different parts of program execution:     --     -- @     -- let s1 = "Initial value"@@ -148,7 +151,7 @@     -- in "Final value: " ++ v     -- @     ---    -- Moreover, we can define a 'Control.Monad.Trans.State.State'+    -- Moreover, we can define a t'Control.Monad.Trans.State.Strict.State'     -- monad which casts the ad hoc state passing pattern as a general     -- pattern known as "monad":     --@@ -186,10 +189,10 @@     -- [@transformers@](https://hackage.haskell.org/package/transformers)     -- and [@mtl@](https://hackage.haskell.org/package/mtl) libraries.     -- The transformer extensions of @State@ and @Either@ are-    -- 'Control.Monad.Trans.State.StateT' and-    -- 'Control.Monad.Trans.State.ExceptT', and the @Mt@ extensions-    -- are 'Control.Monad.State.MonadState' and-    -- 'Control.Monad.Error.MonadError'.  We won't go into more detail+    -- t'Control.Monad.Trans.State.Strict.StateT' and+    -- t'Control.Monad.Trans.ExceptT', and the @mtl@ extensions+    -- are t'Control.Monad.State.Strict.MonadState' and+    -- t'Control.Monad.Except.MonadError'.  We won't go into more detail     -- here because this documentation isn't a transformers or MTL     -- tutorial, but here is an example of an MTL-style function that     -- uses those two effects, and no others:@@ -247,7 +250,7 @@     -- @      -- ** \"Synthetic\" effect systems provide fine-grained effects and encapsulation-    --+     -- | The approach of building effects from smaller pieces by     -- combining algebraic data types, and then interpreting those     -- pieces to "handle" some of the effects can be called the@@ -264,7 +267,7 @@     -- possible effects by handling an effect.      -- *** The downside of synthetic effects-    --+     -- | Unfortunately, synthetic effects have two notable downsides:     -- firstly they have unpredictable performance, and secondly they     -- make it hard to achieve resource safety.  The first point –@@ -304,7 +307,7 @@     -- Brackets](https://academy.fpblock.com/blog/2017/06/tale-of-two-brackets/)".      -- ** @IO@-wrapper effect systems-    --+     -- |     --     -- An alternative to synthetic effects that does allows@@ -396,7 +399,7 @@     -- /-- > exampleBluefin/     -- /-- 55/     -- exampleBluefin :: Int-    -- exampleBluefin = runPureEff $ evalState 0 $ \\st -> do+    -- exampleBluefin = runPureEff $ evalModify 0 $ \\st -> do     --   for_ [1..10] $ \\i -> do     --      modify st (+ i)     --   get st@@ -406,7 +409,7 @@     -- /-- > exampleEffectful/     -- /-- 55/     -- exampleEffectful :: Int-    -- exampleEffectful = runPureEff $ evalState 0 $ do+    -- exampleEffectful = runPureEff $ evalModify 0 $ do     --   for_ [1..10] $ \\i -> do     --      modify (+ i)     --   get@@ -419,7 +422,7 @@     -- If we get the best of both worlds with analytic effect systems,     -- is there a downside?  Yes, the downside is that analytic effect     -- systems do not support multishot continuations, like-    -- 'Control.Monad.Logic.LogicT' implements.  Here's an example of+    -- t'Control.Monad.Logic.LogicT' implements.  Here's an example of     -- using multishot continuations to calculate all sums of paths     -- from root to leaf in a tree.  In the @Branch@ alternative,     -- @allSums t@ is a "multishot" continuation because it is run@@ -455,97 +458,78 @@      -- * A Comparison of effect systems at a glance -    -- ** Mixing effects+    -- ** IO      -- |-    -- - ✅ __IO__: I\/O, state via @IORef@, exceptions via @throw@/@catch@-    -- - ❌ __ST__: State only-    -- - ✅ __MTL__\/__fused-effects__\/__Polysemy__-    -- - ✅ __Bluefin__\/__effectful__+    -- - ✅ __Mixing effects__: I\/O, state via @IORef@, exceptions via @throw@/@catch@+    -- - ❌ __Fine-grained effects__: No distinction between different effects (state, exceptions, I/O, etc.)+    -- - ❌ __Encapsulation__: Can handle exceptions, but doing so is not+    --   reflected in the type+    -- - ✅ __Resource safety__: Operations can be bracketed (see+    --   @Control.Exception.'Control.Exception.bracket'@)+    -- - ✅ __Predictable performance__+    -- - ❌ __Multishot continuations__ -    -- ** Fine-grained Effects+    -- ** ST      -- |-    -- - ❌ __IO__: No distinction between different effects (state, exceptions, I/O, etc.)-    -- - ✅ __ST__: But state only-    -- - ✅ __MTL__\/__fused-effects__\/__Polysemy__: Individual effects are represented at the type level-    -- - ✅ __Bluefin__\/__effectful__: Individual effects are represented at the type level+    -- - ❌ __Mixing effects__: State only+    -- - ✅ __Fine-grained effects__: But state only+    -- - ✅ __Encapsulation__: State effects handled by @runST@ are not present+    --   in the operation's type signature+    -- - ❌ __Resource safety__: State only+    -- - ✅ __Predictable performance__+    -- - ❌ __Multishot continuations__ -    -- ** Encapsulation+    -- ** MTL\/fused-effects\/Polysemy      -- |-    ---    -- - ❌ __IO__: Can handle exceptions, but doing so is not-    --   reflected in the type-    ---    -- - ❌ __ST__: State only-    ---    -- - ✅ __MTL__\/__fused-effects__\/__Polysemy__: Exceptions,-    --   state and other effects handled in the body of an operation+    -- - ✅ __Mixing effectns__+    -- - ✅ __Fine-grained effects__: Individual effects are represented at the type level+    -- - ✅ __Encapsulation__: Exceptions, state and other effects handled in the body of an operation     --   are not present in the operation's type signature-    ---    -- - ✅ __Bluefin__\/__effectful__: Exceptions, state and other-    --   effects handled in the body of an operation are not present-    --   in the operation's type signature+    -- - ❌ __Resource safety__: Difficult to achieve resource safety for arbitrary effects+    -- - ❌ __Predictable performance__: Good performance depends critically on GHC optimization+    -- - ✅ __Multishot continuations__ -    -- ** Resource Safety+    -- ** Bluefin\/effectful      -- |-    -- - ✅ __IO__: Operations can be bracketed (see-    --   @Control.Exception.'Control.Exception.bracket'@)-    ---    -- - ❌ __ST__: State only-    ---    -- - ❌ __MTL__\/__fused-effects__\/__Polysemy__: Difficult to-    --   achieve resource safety for arbitrary effects-    ---    -- - ✅ __Bluefin__\/__effectful__: Operations can be bracketed+    -- - ✅ __Mixing effects__+    -- - ✅ __Fine-grained effects__: Individual effects are represented at the type level+    -- - ✅ __Encapsulatio__: Exceptions, state and other+    --   effects handled in the body of an operation are not present+    --   in the operation's type signature+    -- - ✅ __Resource safety__: Operations can be bracketed     --   (see e.g. @Bluefin.Eff.'Bluefin.Eff.bracket'@) because these     --   effect systems wrap @IO@--    -- ** Predictable Performance--    -- |-    -- - ✅ __IO__: Predictable performance-    -- - ✅ __ST__: Predictable performance-    ---    -- - ❌ __MTL__\/__fused-effects__\/__Polysemy__: Good performance-    --   depends critically on GHC optimization-    ---    -- - ✅ __Bluefin__\/__effectful__: Predictable performance+    -- - ✅ __Predictable performance__: Predictable performance     --   because these effect systems wrap @IO@--    -- ** Multishot continuations--    -- |-    -- - ❌ __IO__-    -- - ❌ __ST__-    -- - ✅ __MTL__\/__fused-effects__\/__Polysemy__-    -- - ❌ __Bluefin__\/__effectful__+    -- - ❌ __Multishot continuations__      -- * Introduction to Bluefin      -- | Bluefin is a Haskell effect system with a new style of API.     -- It is distinct from prior effect systems because effects are-    -- accessed explicitly through value-level handles which occur as-    -- arguments to effectful operations. Handles (such as-    -- 'Bluefin.State.State' handles, which allow access to mutable+    -- accessed explicitly through value-level capabilities which occur as+    -- arguments to effectful operations. Capabilities (such as+    -- 'Bluefin.Capability.Modify.Modify' capabilities, which allow access to mutable     -- state) are introduced by handlers (such as-    -- 'Bluefin.State.evalState', which sets the initial state).-    -- Here's an example where a mutable state effect handle, @sn@, is-    -- introduced by its handler, 'Bluefin.State.evalState'.+    -- 'Bluefin.Capability.Modify.evalModify', which sets the initial state).+    -- Here's an example where a mutable state effect capability, @sn@, is+    -- introduced by its handler, 'Bluefin.Capability.Modify.evalModify'.     --     -- @     -- -- If @n < 10@ then add 10 to it, otherwise     -- -- return it unchanged     -- example1 :: Int -> Int     -- example1 n = 'Bluefin.Eff.runPureEff' $-    --   -- Create a new state handle, sn, and+    --   -- Create a new modify capability, sn, and     --   -- initialize the value of the state to n-    --   'Bluefin.State.evalState' n $ \\sn -> do-    --     n' <- 'Bluefin.State.get' sn+    --   'Bluefin.Capability.Modify.evalModify' n $ \\sn -> do+    --     n' <- 'Bluefin.Capability.Modify.get' sn     --     when (n' < 10) $-    --       'Bluefin.State.modify' sn (+ 10)+    --       'Bluefin.Capability.Modify.modify' sn (+ 10)     --     get sn     -- @     --@@ -556,12 +540,12 @@     -- 12     -- @     ---    -- The handle @sn@ is used in much the same way as an+    -- The capability @sn@ is used in much the same way as an     -- 'Data.STRef.STRef' or 'Data.IORef.IORef'.      -- ** Multiple effects of the same type -    -- | A benefit of value-level effect handles is that it's simple+    -- | A benefit of value-level effect capabilities is that it's simple     -- to have multiple effects of the same type in scope at the same     -- time.  It is simple to disambiguate them, because they are     -- distinct values!  By contrast, existing effect systems require@@ -576,14 +560,14 @@     -- -- to the smaller     -- example2 :: (Int, Int) -> (Int, Int)     -- example2 (m, n) = 'Bluefin.Eff.runPureEff' $-    --   'Bluefin.State.evalState' m $ \\sm -> do-    --     evalState n $ \\sn -> do+    --   'Bluefin.Capability.Modify.evalModify' m $ \\sm -> do+    --     evalModify n $ \\sn -> do     --       do-    --         n' <- 'Bluefin.State.get' sn+    --         n' <- 'Bluefin.Capability.Modify.get' sn     --         m' <- get sm     --     --         if n' < m'-    --           then 'Bluefin.State.modify' sn (+ 10)+    --           then 'Bluefin.Capability.Modify.modify' sn (+ 10)     --           else modify sm (+ 10)     --     --       n' <- get sn@@ -599,11 +583,11 @@     -- (30, 13)     -- @ -    -- ** Exception handles+    -- ** Exception capabilities      -- | Bluefin exceptions are accessed through-    -- 'Bluefin.Exception.Exception' handles.  An @Exception@ handle-    -- is introduced by a handler, such as 'Bluefin.Exception.try',+    -- 'Bluefin.Capability.Throw.Throw' capabilities.  A @Throw@ capability+    -- is introduced by a handler, such as 'Bluefin.Capability.Throw.try',     -- and that handler is where the exception, if thrown, will be     -- handled.  This arrangement differs from normal Haskell     -- exceptions in two ways.  Firstly, every Bluefin exception will@@ -612,26 +596,26 @@     -- only one place – normal Haskell exceptions can be handled in a     -- variety of places, and the closest handler of matching type on     -- the stack will be the one that will be chosen upon-    -- 'Control.Exception.throw'.+    -- @Control.Exception.'Control.Exception.throw'@.     --     -- @example3@ shows how to use Bluefin to calculate the sum of     -- numbers from 1 to @n@, but stop if the sum becomes bigger than-    -- 20.  The exception handle, @ex@, which has type @Exception+    -- 20.  The throw capability, @ex@, which has type @Throw     -- String e@, cannot escape the scope of its handler, @try@.  If     -- thrown it will be handled at that @try@, and nowhere else.     --     -- @     -- example3 :: Int -> Either String Int     -- example3 n = 'Bluefin.Eff.runPureEff' $-    --   'Bluefin.Exception.try' $ \\ex -> do-    --     'Bluefin.State.evalState' 0 $ \\total -> do+    --   'Bluefin.Capability.Throw.try' $ \\ex -> do+    --     'Bluefin.Capability.Modify.evalModify' 0 $ \\total -> do     --       for_ [1..n] $ \\i -> do-    --          soFar <- 'Bluefin.State.get' total+    --          soFar <- 'Bluefin.Capability.Modify.get' total     --          when (soFar > 20) $ do-    --            'Bluefin.Exception.throw' ex ("Became too big: " ++ show soFar)-    --          'Bluefin.State.put' total (soFar + i)+    --            'Bluefin.Capability.Throw.throw' ex ("Became too big: " ++ show soFar)+    --          'Bluefin.Capability.Modify.put' total (soFar + i)     ---    --       'Bluefin.State.get' total+    --       'Bluefin.Capability.Modify.get' total     -- @     --     -- @@@ -644,68 +628,68 @@     -- ** Effect scoping      -- | Bluefin's use of the type system is very similar to-    -- "Control.Monad.ST": it ensures that a handle can never escape+    -- "Control.Monad.ST": it ensures that a capability can never escape     -- the scope of its handler.  That is, once the handler has-    -- finished running there is no way you can use the handle+    -- finished running there is no way you can use the capability     -- anymore. For an example of a correctly-scoped function see-    -- @correctlyScoped@ below.  It uses Bluefin’s @State@ handle to+    -- @correctlyScoped@ below.  It uses Bluefin’s @Modify@ capability to     -- compute the sum of the numbers 1 to 10, before multiplying the-    -- result by 20. In @correctlyScoped@ the @State@ handle is scoped-    -- to its handler, @evalState@, and everything works as expected:+    -- result by 20. In @correctlyScoped@ the @Modify@ capability is scoped+    -- to its handler, @evalModify@, and everything works as expected:     --     -- @     -- -- /Result: 1100/     -- correctlyScoped :: Eff es Integer     -- correctlyScoped = do     --   -- /Initial state 0/-    --   r \<- 'Bluefin.State.evalState' 0 $ \\st -> do-    --     -- The 'Bluefin.State.State' handle "st" is scoped to the-    --     -- handler that introduced it, evalState,+    --   r \<- 'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do+    --     -- The 'Bluefin.Capability.Modify.Modify' handle "st" is scoped to the+    --     -- handler that introduced it, evalModify,     --     -- and therefore it can only be used within     --     -- this do block.     --     --     -- /Add up the numbers 1 to 10/     --     for_ [1..10] $ \\i -> do-    --       'Bluefin.State.modify' st (+ i)+    --       'Bluefin.Capability.Modify.modify' st (+ i)     --     --     -- /Get the result/-    --     'Bluefin.State.get' st+    --     'Bluefin.Capability.Modify.get' st     --     --   pure (r * 20)     -- @     --     -- Now let's look at an incorrectly-scoped example,-    -- @incorrectlyScoped@. It attempts to pass the state handle @st@-    -- out of the scope of @evalState@:+    -- @incorrectlyScoped@. It attempts to pass the modify capability @st@+    -- out of the scope of @evalModify@:     --     -- @     -- incorrectlyScoped :: Eff es Integer     -- incorrectlyScoped = do     --   -- /Initial state 0/-    --   (total, st) \<- 'Bluefin.State.evalState' 0 $ \\st -> do+    --   (total, st) \<- 'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do     --     -- /Add up the numbers 1 to 10/     --     for_ [1..10] $ \\i -> do-    --       'Bluefin.State.modify' st (+ i)+    --       'Bluefin.Capability.Modify.modify' st (+ i)     --     --     -- /Get the result/-    --     r <- 'Bluefin.State.get' st+    --     r <- 'Bluefin.Capability.Modify.get' st     --     --     -- /Pass out the result, and try to pass the/-    --     -- /'Bluefin.State.State' handle outside its scope, i.e. this/-    --     -- /do block introduced by evalState/+    --     -- /'Bluefin.Capability.Modify.Modify' capability outside its scope, i.e. this/+    --     -- /do block introduced by evalModify/     --     pure (r, st)     --     --   modify st (* 20)     --   get st     -- @     ---    -- The type system prevents us from passing the @State@ handle out+    -- The type system prevents us from passing the @Modify@ capability out     -- of its scope, giving this error message:     --     -- @     -- • Couldn't match type ‘e0’ with ‘e’-    --   Expected: (Integer, State Integer e0)-    --     Actual: (Integer, State Integer e)+    --   Expected: (Integer, Modify Integer e0)+    --     Actual: (Integer, Modify Integer e)     --     because type variable ‘e’ would escape its scope     -- @ @@ -715,19 +699,19 @@     -- pattern which looks like     --     -- @-    -- (e1 :> es, ...) -> \<Handle\> e1 -> ... -> Eff es r+    -- (e1 \<: es, ...) -> \<Capability\> e1 -> ... -> Eff es r     -- @     ---    -- Here @\<Handle\>@ could be, for example, @State Int@,-    -- @Exception String@ or @IOE@.  Consider the function below,+    -- Here @\<Capability\>@ could be, for example, @Modify Int@,+    -- @Throw String@ or @IOE@.  Consider the function below,     -- @incrementReadLine@. It reads integers from standard input,     -- accumulates them into a state; it returns when it reads the     -- input integer @0@ and it throws an exception if it encounters     -- an input line it cannot parse.     ---    -- Firstly, let's look at the arguments, which are all handles to-    -- Bluefin effects.  There is a state handle, an exception handle,-    -- and an IO handle, which allow modification of an @Int@ state,+    -- Firstly, let's look at the arguments, which are all capabilities.+    -- There is a modify capability, a throw capability,+    -- and an IO capability, which allow modification of an @Int@ state,     -- throwing a @String@ exception, and performing @IO@ operations     -- respectively.  They are each tagged with a different effect     -- type, @e1@, @e2@ and @e3@ respectively, which are always kept@@ -742,10 +726,10 @@     -- Finally, let's look at the constraints.  They are what tie     -- together the effect tags of the arguments to the effect tag of     -- the result.  For every argument effect tag @en@ we have a-    -- constraint @en :> es@.  That tells us the that effect handle+    -- constraint @en \<: es@.  That tells us the that capability     -- with tag @en@ is allowed to be used within the effectful-    -- computation.  If we didn't have the @e1 :> es@ constraint, for-    -- example, that would tell us that the @State Int e1@ isn't+    -- computation.  If the @e1 \<: es@ constraint, for+    -- example, were not required that would tell us that the @Modify Int e1@ isn't     -- actually used anywhere in the computation.     --     -- GHC and editor tools like HLS do a good job of inferring these@@ -753,9 +737,9 @@     --     -- @     -- incrementReadLine ::-    --   (e1 :> es, e2 :> es, e3 :> es) =>-    --   State Int e1  ->-    --   Exception String e2  ->+    --   (e1 \<: es, e2 \<: es, e3 \<: es) =>+    --   Modify Int e1  ->+    --   Throw String e2  ->     --   IOE e3 ->     --   Eff es ()     -- incrementReadLine state exception io = do@@ -763,39 +747,39 @@     --     line <- 'Bluefin.IO.effIO' io getLine     --     i <- case 'Text.Read.readMaybe' line of     --       Nothing ->-    --         'Bluefin.Exception.throw' exception ("Couldn't read: " ++ line)+    --         'Bluefin.Capability.Throw.throw' exception ("Couldn't read: " ++ line)     --       Just i ->     --         pure i     --     --     when (i == 0) $     --       'Bluefin.Jump.jumpTo' break     ---    --     'Bluefin.State.modify' state (+ i)+    --     'Bluefin.Capability.Modify.modify' state (+ i)     -- @     --     -- Now let's look at how we can run such a function.  Each effect     -- must be handled by a corresponding handler, for example-    -- 'Bluefin.State.runState' for the state effect,-    -- 'Bluefin.Exception.try' for the exception effect and-    -- 'Bluefin.Eff.runEff_' for the @IO@ effect.  The type signatures+    -- 'Bluefin.Capability.Modify.runModify' for the state effect,+    -- 'Bluefin.Capability.Throw.try' for the exception effect and+    -- 'Bluefin.Eff.runEff' for the @IO@ effect.  The type signatures     -- of handlers also follow a common pattern, which looks like     --     -- @     -- (forall e. \<Handle\> e -> Eff (e :& es) a) -> Eff es r     -- @     ---    -- This means that the effect @e@, corresponding to the handle-    -- @\<Handle\> e@, has been handled and removed from the set of+    -- This means that the effect tag @e@, corresponding to the capability+    -- @\<Capability\> e@, has been handled and removed from the set of     -- remaining effects, @es@.  (The signatures for-    -- 'Bluefin.Eff.runEff_' and 'Bluefin.Eff.runPureEff' are slightly+    -- 'Bluefin.Eff.runEff' and 'Bluefin.Eff.runPureEff' are slightly     -- different because they remove @Eff@ itself.)  Here, then, is     -- how we can run @incrementReadLine@:     --     -- @     -- runIncrementReadLine :: IO (Either String Int)-    -- runIncrementReadLine = 'Bluefin.Eff.runEff_' $ \\io -> do-    --   'Bluefin.Exception.try' $ \\exception -> do-    --     ((), r) \<- 'Bluefin.State.runState' 0 $ \\state -> do+    -- runIncrementReadLine = 'Bluefin.Eff.runEff' $ \\io -> do+    --   'Bluefin.Capability.Throw.try' $ \\exception -> do+    --     ((), r) \<- 'Bluefin.Capability.Modify.runModify' 0 $ \\state -> do     --       incrementReadLine state exception io     --     pure r     --@@ -826,7 +810,7 @@     -- ** @effectful@      -- | The major difference between Bluefin and @effectful@ is that in-    -- Bluefin effects are represented as value-level handles whereas+    -- Bluefin effects are represented as value-level capabilities whereas     -- in @effectful@ they are represented only at the type level.     -- @effectful@ could be described as "a well-typed implementation of     -- the @ReaderT@ @IO@ pattern", and Bluefin could be described as@@ -852,22 +836,22 @@      -- | Bluefin has a similar implementation style to @effectful@.     -- t'Bluefin.Eff.Eff' is an opaque wrapper around 'IO',-    -- t'Bluefin.State.State' is an opaque wrapper around-    -- 'Data.IORef.IORef', and 'Bluefin.Exception.throw' throws an-    -- actual @IO@ exception.  t'Bluefin.Coroutine.Coroutine' is+    -- t'Bluefin.Capability.Modify.Modify' is an opaque wrapper around+    -- 'Data.IORef.IORef', and 'Bluefin.Capability.Throw.throw' throws an+    -- actual @IO@ exception.  t'Bluefin.Capability.Request.Request' is     -- implemented simply as a function.     --     -- @     -- newtype t'Bluefin.Eff.Eff' (es :: 'Bluefin.Eff.Effects') a = 'Bluefin.Internal.UnsafeMkEff' (IO a)-    -- newtype t'Bluefin.State.State' s (st :: Effects) = 'Bluefin.Internal.UnsafeMkState' (IORef s)-    -- newtype t'Bluefin.Coroutine.Coroutine' a b (s :: Effects) = 'Bluefin.Internal.UnsafeMkCoroutine' (a -> IO b)+    -- newtype t'Bluefin.Capability.Modify.Modify' s (st :: Effects) = 'Bluefin.Internal.UnsafeMkState' (IORef s)+    -- newtype t'Bluefin.Capability.Request.Request' a b (s :: Effects) = 'Bluefin.Internal.UnsafeMkCoroutine' (a -> IO b)     -- @     --     -- The type parameters of kind t'Bluefin.Eff.Effects' are phantom     -- type parameters which track which effects can be used in an     -- operation. Bluefin uses them to ensure that effects cannot     -- escape the scope of their handler, in the same way that the-    -- type parameter to the 'Control.Monad.ST.ST' monad ensures that+    -- type parameter to the t'Control.Monad.ST.ST' monad ensures that     -- mutable state references cannot escape     -- 'Control.Monad.ST.runST'.  When the type system indicates that     -- there are no unhandled effects it is safe to run the underlying@@ -895,16 +879,16 @@     -- @     -- countPositivesNegatives :: [Int] -> String     -- countPositivesNegatives is = 'Bluefin.Eff.runPureEff' $-    --   'Bluefin.State.evalState' (0 :: Int) $ \\positives -> do-    --       r \<- 'Bluefin.Exception.try' $ \\ex ->-    --           evalState (0 :: Int) $ \\negatives -> do+    --   'Bluefin.Capability.Modify.evalModify' (0 :: Int) $ \\positives -> do+    --       r \<- 'Bluefin.Capability.Throw.try' $ \\ex ->+    --           evalModify (0 :: Int) $ \\negatives -> do     --               for_ is $ \\i -> do     --                   case compare i 0 of-    --                       GT -> 'Bluefin.State.modify' positives (+ 1)+    --                       GT -> 'Bluefin.Capability.Modify.modify' positives (+ 1)     --                       EQ -> throw ex ()     --                       LT -> modify negatives (+ 1)     ---    --               p <- 'Bluefin.State.get' positives+    --               p <- 'Bluefin.Capability.Modify.get' positives     --               n <- get negatives     --     --               pure $
+ src/Bluefin/Capability.hs view
@@ -0,0 +1,40 @@+module Bluefin.Capability+  ( -- * Historical commentary++    -- | Bluefin is in a transitionary phase moving away from the old+    -- terminology of "handle" and naming handles/effects based on+    -- MTL\/transformers style names+    -- (e.g. @Exception@\/@Reader@\/@Stream@) and moving towards+    -- calling these things "capabilities" and naming them after their+    -- main operation (e.g. @Throw@\/@Ask@\/@Yield@).  You are+    -- encouraged to use the API beneath @Bluefin.Capability@ because+    -- that will be the supported API in the future.+    --+    -- You are encouraged to change your usage of the old modules on+    -- the left to the new modules on the right:+    --+    -- +------------------------+------------------------------------------++    -- | Old                    | New                                      |+    -- +========================+==========================================++    -- | "Bluefin.Reader"       | "Bluefin.Capability.Ask"                 |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.HandleReader" | "Bluefin.Capability.AskCapability"       |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.Consume"      | "Bluefin.Capability.Await"               |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.Jump"         | "Bluefin.Capability.JumpTo"              |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.State"        | "Bluefin.Capability.Modify"              |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.Coroutine"    | "Bluefin.Capability.Request"             |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.EarlyReturn"  | "Bluefin.Capability.ReturnEarly"         |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.Writer"       | "Bluefin.Capability.Tell"                |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.Exception"    | "Bluefin.Capability.Throw"               |+    -- +------------------------+------------------------------------------++    -- | "Bluefin.Stream"       | "Bluefin.Capability.Yield"               |+    -- +------------------------+------------------------------------------++  )+where
+ src/Bluefin/Capability/Ask.hs view
@@ -0,0 +1,21 @@+module Bluefin.Capability.Ask+  ( -- | 'Ask' is Bluefin's version of the+    -- "Control.Monad.Trans.Reader" monad.  'local' allows you to+    -- locally override the @ask@ed value in a well-scoped way.  The+    -- original value will be restored when you exit the @local@ block+    -- regardless of whether the exit was normal or via an exception.++    -- * Capability+    Ask,++    -- * Handlers+    runAsk,++    -- * Effectful operations+    ask,+    asks,+    local,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/AskCapability.hs view
@@ -0,0 +1,29 @@+-- | 'AskCapability' is like t'Bluefin.Capability.Ask.Ask', generalized to+-- work for arbitrary t'Bluefin.Compound.Handle's.  'localCapability'+-- locally overrides the value of a capability in a well-scoped way.  The+-- original capability will be restored when you exit the @localCapability@+-- block regardless of whether the exit was normal or via an+-- exception.+--+-- @AskCapability@ supports functionality similiar to @effectful@'s+-- [@interpose@](https://hackage.haskell.org/package/effectful-core/docs/Effectful-Dispatch-Dynamic.html#v:interpose)+-- and @polysemy@'s+-- [@intercept@](https://hackage.haskell.org/package/polysemy/docs/Polysemy.html#v:intercept),+-- that is, locally augmenting an effect with new behaviors.  If you+-- want to do the same in Bluefin you may want to start with+-- @Bluefin.GadtEffect.'Bluefin.GadtEffect.interpose`@.+module Bluefin.Capability.AskCapability+  ( -- * Handle+    AskCapability,++    -- * Handlers+    runAskCapability,++    -- * Effectful operations+    askCapability,+    asksCapability,+    localCapability,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/Await.hs view
@@ -0,0 +1,22 @@+module Bluefin.Capability.Await+  ( -- | 'Await' allows you to await values during the execution of+    -- a Bluefin operation.  It provides similar functionality to+    -- @await@ from Conduit or Pipes.+    --+    -- For information about prompt finalization/resource safety when+    -- using Bluefin @Consume@s, see "Bluefin.Coroutine".++    -- * Capability+    Await,++    -- * Handlers+    eachAwait,+    awaitYield,++    -- * Effectful operations+    await,+    takeAwait,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/JumpTo.hs view
@@ -0,0 +1,18 @@+module Bluefin.Capability.JumpTo+  ( -- | 'JumpTo' allows you to jump back to a previously-set location.+    -- A "jump" is equivalent to an untyped early return, or more+    -- precisely an early return of type @()@, which is itself an+    -- exception of type @()@.++    -- * Capability+    JumpTo,++    -- * Handlers+    withJumpTo,++    -- * Effectful operations+    jumpTo,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/Modify.hs view
@@ -0,0 +1,17 @@+module Bluefin.Capability.Modify+  ( -- * Capability+    Modify,++    -- * Handlers+    evalModify,+    runModify,+    withModify,++    -- * Effectful operations+    get,+    put,+    modify,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/Request.hs view
@@ -0,0 +1,89 @@+module Bluefin.Capability.Request+  ( -- | @Request@ allows to yield values and await the result. You+    -- might want to start with "Bluefin.Capability.Yield", which is+    -- the most common way to use @Request@s.++    -- ** Prompt finalization/resource safety++    -- | Bluefin+    -- t'Bluefin.Capability.Yield.Yield' \/ t'Bluefin.Capability.Await.Await' \/ t'Bluefin.Capability.Request.Request'+    -- computations have much better resource safety properties than+    -- Conduit and Pipes.  You can use+    -- @Bluefin.Eff.'Bluefin.Eff.bracket'@ within a streaming+    -- computation and the acquired resource is guaranteed to be+    -- released and the end of the bracket, rather than at the end of+    -- the @ResourceT@ scope as it is the case in Conduit and Pipes.+    -- See the blog post [Bluefin streams finalize+    -- promptly](https://h2.jaguarpaw.co.uk/posts/bluefin-streams-finalize-promptly/)+    -- for more details.++    -- ** Running coroutines that communicate via @Request@s++    -- | Bluefin operations can be executed as coroutines using+    --  'connectRequests' ([Wikipedia+    --  suggests](https://en.wikipedia.org/wiki/Coroutine#Definition_and_types)+    --  that such coroutines are "second-class stackful coroutines").+    --  Two coroutines run in this way communicate synchronously by+    --  using @Request@s to interact with a bi-directional+    --  channel. This means that such coroutines are often run+    --  exclusively for what they communicate via this channel, not+    --  for their return value.+    --+    -- @Request@s used in this way work a bit like UNIX pipes: there+    -- is a downstream consumer and an upstream generator. For every+    -- pair of such communicating coroutines there are two ends,+    -- represented with the capabilities @Request a b@ and @Request b+    -- a@. The first parameter to @Request@ is the type that can be+    -- /sent from/ that end, while the second parameter is the type+    -- that will subsequently be /received by/ that end. This explains+    -- the symmetry in the capabilities: what one end sends the other+    -- receives. The implication is that upstream and downstream+    -- exchange messages with each other at the same+    -- time. Additionally, there is a clear order of communication+    -- from the start (in Bluefin, communication is started by+    -- upstream).+    --+    -- 'request' is the only effectful operation required: a @Request+    -- a b@ capability that represents one end of a channel sends @a@s+    -- and receives a @b@s. For many use cases, upstream does not need+    -- to know anything from downstream (dually: downstream does not+    -- need to communicate anything to upstream) except that+    -- downstream is making a new request, so the capabilities that+    -- describe most channels are \"@Request a ()@\" and \"@Request ()+    -- a@\". Bluefin provides synonyms for these:+    -- @'Bluefin.Capability.Yield.Yield' a@ and+    -- @'Bluefin.Capability.Await.Await' a@, respectively. The+    -- specializations of @request@ for @Yield@ and @Await@ are called+    -- 'Bluefin.Capability.Yield.yield' and+    -- 'Bluefin.Capability.Await.await'.  Coroutines that send data in+    -- only one direction like this can be created using 'awaitYield'.+    --+    -- Because the message exchange occurs synchronously, when yielding,+    -- the upstream will block until the downstream awaits. The converse+    -- is also true: when downstream awaits, it will block until upstream+    -- yields.+    --+    -- Any Bluefin effectful operation that takes a @Request@+    -- capability as an argument can be run as coroutine using+    -- 'connectRequests' by providing a second effectful operation+    -- as its counterpart on the other end of the channel.+    --+    -- For simple applications one may not need @connectRequests@ at+    -- all, because specific handlers are already provided by+    -- Bluefin. See the \"Handlers\" sections of the+    -- "Bluefin.Capability.Yield" and "Bluefin.Capability.Await"+    -- modules.++    -- * Capability+    Request,++    -- * Handlers+    forEach,+    connectRequests,++    -- * Effectful operations+    request,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/ReturnEarly.hs view
@@ -0,0 +1,17 @@+module Bluefin.Capability.ReturnEarly+  ( -- | @Bluefin.ReturnEarly@ allows to define a block from which you can+    -- return early.  Early return is implemented as an exception, and+    -- its API is just an alternate interface to exceptions.++    -- * Capability+    ReturnEarly,++    -- * Handlers+    withReturnEarly,++    -- * Effectful operations+    returnEarly,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/Tell.hs view
@@ -0,0 +1,19 @@+module Bluefin.Capability.Tell+  ( -- | In most cases you'll probably prefer t'Bluefin.Capability.Yield.Yield'+    -- to @Tell@, but @Tell@ can still be useful in some cases,+    -- for example with @Data.Monoid.'Data.Monoid.Any'@ to determine+    -- whether an event ever occurred.++    -- * Capability+    Tell,++    -- * Handlers+    runTell,+    execTell,++    -- * Effectful operations+    tell,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/Throw.hs view
@@ -0,0 +1,16 @@+module Bluefin.Capability.Throw+  ( -- * Capability+    Throw,++    -- * Handlers+    try,+    handle,+    catch,++    -- * Effectful operations+    throw,+    rethrowIO,+  )+where++import Bluefin.Internal
+ src/Bluefin/Capability/Yield.hs view
@@ -0,0 +1,35 @@+module Bluefin.Capability.Yield+  ( -- | 'Yield' allows you to yield values during the execution of a+    -- Bluefin operation.  It provides similar functionality to+    -- Python's @yield@.  The handler of the 'Yield' will either+    -- handle each element as soon as it is yielded (for example+    -- 'forEach') or gather all yielded elements into a list (for+    -- example 'yieldToList').+    --+    -- For information about prompt finalization/resource safety when+    -- using Bluefin @Yield@s, see "Bluefin.Capability.Request".++    -- * Capability+    Yield,++    -- * Handlers+    forEach,+    yieldToList,+    yieldToReverseList,+    withYieldToList,+    ignoreYield,+    enumerate,+    enumerateFrom,+    mapMaybe,+    catMaybes,+    awaitYield,++    -- * Effectful operations+    yield,+    inFoldable,+    cycleToYield,+    takeAwait,+  )+where++import Bluefin.Internal
+ src/Bluefin/CloneableHandle.hs view
@@ -0,0 +1,91 @@+-- | @Bluefin.CloneableHandle@ defines the 'CloneableHandle' class,+-- whose purpose is to support 'withEffToIOCloneHandle'.+module Bluefin.CloneableHandle+  ( -- | 'withEffToIOCloneHandle' is an @IO@ unlifting function that+    -- clones its handle each time it runs @Eff@ in @IO@.  This is+    -- convenient when the unlifting function is being used to fork+    -- threads, since Bluefin state is not threadsafe.  Be careful+    -- when you use it, because it can be used to throw away the+    -- effect tag on a Bluefin @Eff@ action due to this part of+    -- its type (here throwing away @e@):+    --+    -- @+    -- (forall e. IOE e -> h e -> Eff e r) -> IO r+    -- @+    --+    -- It is only safely used when you do not allow any effects to+    -- escape their scope, so we suggest that you use it sparingly to+    -- define reusable combinators which themselves are safe.  For+    -- example, here is how you could write an equivalent of @async@'s+    -- @race@ primitive:+    --+    -- @+    -- bluefinRace ::+    --   ('CloneableHandle' h, e1 \<: es) =>+    --   t'Bluefin.IO.IOE' e1 ->+    --   h es ->+    --   (forall e. IOE e -> h e -> t'Bluefin.Eff.Eff' e r) ->+    --   (forall e. IOE e -> h e -> Eff e r) ->+    --   Eff es r+    -- bluefinRace io h m1 m2 = withEffToIOCloneHandle io h $ \\runInIO -> do+    --  either id id+    --    \<$\> Control.Concurrent.Async.race+    --      (runInIO $ \\io' h' -> m1 io' h')+    --      (runInIO $ \\io' h' -> m2 io' h')+    -- @+    --+    -- Then you can safely use it to race Bluefin @Eff@ actions:+    --+    -- @+    -- example :: IO ()+    -- example = 'Bluefin.Eff.runEff' $ \\io -> 'Bluefin.State.evalState' 0 $ \\st -> do+    --   r \<- 'Bluefin.Exception.try' $ \\ex -> do+    --     bluefinRace+    --       io+    --       (MkMyHandle ('Bluefin.Handle.mapHandle' ex) (mapHandle st))+    --       ( \\_ (MkMyHandle ex' st') -> do+    --           'Bluefin.State.modify' st' (subtract 2000)+    --           'Bluefin.Exception.throw' ex' "Aborting from branch 1"+    --       )+    --       ( \\_ (MkMyHandle _ st') -> do+    --           modify st' (+ 3000)+    --           pure (2 :: Int)+    --       )+    --+    --   s <- 'Bluefin.State.get' st+    --   'Bluefin.IO.effIO' io (print r)+    --   effIO io (putStrLn ("State started at 0 and was cloned. Now: " <> show s))+    -- @+    --+    -- You can see from the output that the actions were raced as+    -- expected, and the @State@ was cloned so that changes to it in+    -- the branches of @race@ did not affect the original @State@.+    --+    -- @+    -- -- Run one time (the first thread was faster)+    -- ghci> example+    -- Right 2+    -- State started at 0 and was cloned. Now: 0+    -- -- Run another time (the second thread was faster)+    -- ghci> example+    -- Left "Aborting from branch 1"+    -- State started at 0 and was cloned. Now: 0+    -- @+    --+    -- Note that @withEffToIOCloneHandle@ only allows access to /one/+    -- external @Handle@ within it, so if you have several you'd like+    -- to use you'll have to define a new handle that bundles them+    -- together.+    withEffToIOCloneHandle,++    -- * @CloneableHandle@+    CloneableHandle,+    GenericCloneableHandle (MkGenericCloneableHandle),+    GCloneableHandle,++    -- * @GHC.Generics@ re-exports+    Generic1,+  )+where++import Bluefin.Internal.CloneableHandle
src/Bluefin/Compound.hs view
@@ -7,22 +7,22 @@     -- creating your own effects is equivalent to creating your own     -- data types.  We just use the techniques we know and love from     -- Haskell!  For example, if I want to make a "counter" effect-    -- that allows me to increment a counter then I can wrap a 'Bluefin.State.State'-    -- handle in a newtype:+    -- that allows me to increment a counter then I can wrap a 'Bluefin.Capability.Modify.Modify'+    -- capability in a newtype:     --     -- @-    -- newtype Counter1 e = MkCounter1 ('Bluefin.State.State' Int e)+    -- newtype Counter1 e = MkCounter1 ('Bluefin.Capability.Modify.Modify' Int e)     ---    -- incCounter1 :: (e :> es) => Counter1 e -> 'Bluefin.Eff.Eff' es ()-    -- incCounter1 (MkCounter1 st) = 'Bluefin.State.modify' st (+ 1)+    -- incCounter1 :: (e \<: es) => Counter1 e -> 'Bluefin.Eff.Eff' es ()+    -- incCounter1 (MkCounter1 st) = 'Bluefin.Capability.Modify..modify' st (+ 1)     --     -- runCounter1 ::     --   (forall e. Counter1 e -> Eff (e :& es) r) ->     --   Eff es Int     -- runCounter1 k =-    --   'Bluefin.State.evalState' 0 $ \\st -> do+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do     --     _ <- k (MkCounter1 st)-    --     'Bluefin.State.get' st+    --     'Bluefin.Capability.Modify.get' st     -- @     --     -- Running the handler tells me the number of times I incremented@@ -47,29 +47,29 @@     -- normal approach we use to wrap multiple values into a single     -- value: define a new data type with multiple fields.  There's a     -- caveat to this approach, but before we address the caveat let's-    -- see the approach in action.  Here we define a new handle,-    -- @Counter2@, that contains a 'Bluefin.State.State' and 'Bluefin.Exception.Exception' handle+    -- see the approach in action.  Here we define a new capabiilty,+    -- @Counter2@, that contains a 'Bluefin.Capability.Modify.Modify' and 'Bluefin.Capability.Throw.Throw' capability     -- within it.  That allows us to increment the counter and throw     -- an exception when we hit a limit.     --     -- @-    -- data Counter2 e1 e2 = MkCounter2 ('Bluefin.State.State' Int e1) ('Bluefin.Exception.Exception' () e2)+    -- data Counter2 e1 e2 = MkCounter2 ('Bluefin.Capability.Modify.Modify' Int e1) ('Bluefin.Capability.Throw.Throw' () e2)     ---    -- incCounter2 :: (e1 :> es, e2 :> es) => Counter2 e1 e2 -> 'Bluefin.Eff.Eff' es ()+    -- incCounter2 :: (e1 \<: es, e2 \<: es) => Counter2 e1 e2 -> 'Bluefin.Eff.Eff' es ()     -- incCounter2 (MkCounter2 st ex) = do-    --   count <- 'Bluefin.State.get' st+    --   count <- 'Bluefin.Capabiilty.Modify.get' st     --   when (count >= 10) $-    --     'Bluefin.Exception.throw' ex ()-    --   'Bluefin.State.put' st (count + 1)+    --     'Bluefin.Capability.Throw.throw' ex ()+    --   'Bluefin.Capability.Modify.put' st (count + 1)     --     -- runCounter2 ::     --   (forall e1 e2. Counter2 e1 e2 -> Eff (e2 :& e1 :& es) r) ->     --   Eff es Int     -- runCounter2 k =-    --   'Bluefin.State.evalState' 0 $ \\st -> do-    --     _ \<- 'Bluefin.Exception.try' $ \\ex -> do+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do+    --     _ \<- 'Bluefin.Capability.Throw.try' $ \\ex -> do     --       k (MkCounter2 st ex)-    --     'Bluefin.State.get' st+    --     'Bluefin.Capability.Modify.get' st     -- @     --     -- We can see that attempting to increment the counter fovever@@ -88,7 +88,7 @@     -- @     --     -- The flaw of this approach is that you expose one effect-    -- parameter for each handle in the data type.  That's rather+    -- parameter for each capability in the data type.  That's rather     -- cumbersome!  We can do better.      -- ** Wrap multiple effects, a better approach@@ -97,27 +97,27 @@     -- expose a single one.  To make this work we have to define our     -- handler in a slightly different way.  Firstly we apply     -- 'useImplIn' to the effectful operation @k@ and secondly we-    -- apply 'mapHandle' to each of the handles out of which we create-    -- our compound handle.  Everything else remains the same.+    -- apply 'mapHandle' to each of the capabiilties out of which we create+    -- our compound capability.  Everything else remains the same.     --     -- @-    -- data Counter3 e = MkCounter3 ('Bluefin.State.State' Int e) ('Bluefin.Exception.Exception' () e)+    -- data Counter3 e = MkCounter3 ('Bluefin.Capability.Modify.Modify' Int e) ('Bluefin.Capability.Throw.Throw' () e)     ---    -- incCounter3 :: (e :> es) => Counter3 e -> Eff es ()+    -- incCounter3 :: (e \<: es) => Counter3 e -> Eff es ()     -- incCounter3 (MkCounter3 st ex) = do-    --   count <- 'Bluefin.State.get' st+    --   count <- 'Bluefin.Capability.Modify.get' st     --   when (count >= 10) $-    --     'Bluefin.Exception.throw' ex ()-    --   'Bluefin.State.put' st (count + 1)+    --     'Bluefin.Capability.Throw.throw' ex ()+    --   'Bluefin.Capability.Modify.put' st (count + 1)     --     -- runCounter3 ::     --   (forall e. Counter3 e -> Eff (e :& es) r) ->     --   Eff es Int     -- runCounter3 k =-    --   'Bluefin.State.evalState' 0 $ \\st -> do-    --     _ \<- 'Bluefin.Exception.try' $ \\ex -> do+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do+    --     _ \<- 'Bluefin.Capability.Throw.try' $ \\ex -> do     --       'useImplIn' k (MkCounter3 ('mapHandle' st) (mapHandle ex))-    --     'Bluefin.State.get' st+    --     'Bluefin.Capability.Modify.get' st     -- @     --     -- The example works as before:@@ -141,19 +141,19 @@     -- though: we can leave an effect unhandled to be handled by a     -- different handler at a higher level.  This must /always/ be the     -- case for 'Bluefin.IO.IOE', which can only be handled at the top-    -- level by 'Bluefin.Eff.runEff_'.  Let's see what it looks like to+    -- level by 'Bluefin.Eff.runEff'.  Let's see what it looks like to     -- wrap @IOE@ and provide an API which allows a subset of @IO@     -- operations.     --     -- @     -- newtype Counter3B e = MkCounter3B ('Bluefin.IO.IOE' e)     ---    -- incCounter3B :: (e :> es) => Counter3B e -> 'Bluefin.Eff.Eff' es ()+    -- incCounter3B :: (e \<: es) => Counter3B e -> 'Bluefin.Eff.Eff' es ()     -- incCounter3B (MkCounter3B io) =     --   effIO io (putStrLn "You tried to increment the counter")     --     -- runCounter3B ::-    --   (e1 :> es) =>+    --   (e1 \<: es) =>     --   IOE e1 ->     --   (forall e. Counter3B e -> Eff (e :& es) r) ->     --   Eff es r@@ -162,7 +162,7 @@     --     -- @     -- exampleCounter3B :: IO ()-    -- exampleCounter3B = 'Bluefin.Eff.runEff_' $ \\io -> runCounter3B io $ \\c -> do+    -- exampleCounter3B = 'Bluefin.Eff.runEff' $ \\io -> runCounter3B io $ \\c -> do     --   incCounter3B c     --   incCounter3B c     --   incCounter3B c@@ -191,32 +191,32 @@     --     -- @     -- data Counter4 e-    --   = MkCounter4 ('Bluefin.State.State' Int e) ('Bluefin.Exception.Exception' () e) ('Bluefin.Stream.Stream' String e)+    --   = MkCounter4 ('Bluefin.Capability.Modify.Modify' Int e) ('Bluefin.Capability.Throw.Throw' () e) ('Bluefin.Stream.Stream' String e)     ---    -- incCounter4 :: (e :> es) => Counter4 e -> Eff es ()+    -- incCounter4 :: (e \<: es) => Counter4 e -> Eff es ()     -- incCounter4 (MkCounter4 st ex y) = do-    --   count <- 'Bluefin.State.get' st+    --   count <- 'Bluefin.Capability.Modify.get' st     --     --   when (even count) $     --     'Bluefin.Stream.yield' y "Count was even"     --     --   when (count >= 10) $-    --     'Bluefin.Exception.throw' ex ()+    --     'Bluefin.Capability.Throw.throw' ex ()     ---    --   'Bluefin.State.put' st (count + 1)+    --   'Bluefin.Capability.Modify.put' st (count + 1)     ---    -- getCounter4 :: (e :> es) => Counter4 e -> String -> Eff es Int+    -- getCounter4 :: (e \<: es) => Counter4 e -> String -> Eff es Int     -- getCounter4 (MkCounter4 st _ y) msg = do     --   yield y msg     --   get st     --     -- runCounter4 ::-    --   (e1 :> es) =>+    --   (e1 \<: es) =>     --   Stream String e1 ->     --   (forall e. Counter4 e -> Eff (e :& es) r) ->     --   Eff es Int     -- runCounter4 y k =-    --   evalState 0 $ \\st -> do+    --   evalModify 0 $ \\st -> do     --     _ \<- try $ \\ex -> do     --       'useImplIn' k (MkCounter4 ('mapHandle' st) (mapHandle ex) (mapHandle y))     --     get st@@ -244,55 +244,53 @@     -- new effects implemented in terms of specific other effects.  We     -- can also define dynamic effects, whose implementation is left     -- abstract, to be defined in the handler.  To do that we create a-    -- handle that is a record of functions.  To run an effectful+    -- capability that is a record of functions.  To run an effectful     -- operation we call one of the functions from the record.  We     -- define the record in the handler.  Here @incCounter5Impl@ and     -- @getCounter5Impl@ are exactly the same as @incCounter4@ and     -- @getCounter4@ were, they're just defined in the handler.  In     -- order to be used polymorphically, the actually effectful     -- functions we call, @incCounter5@ and @getCounter5@ are derived-    -- from the record fields by applying 'makeOp'.+    -- from the record fields.     --     -- @     -- data Counter5 e = MkCounter5-    --   { incCounter5Impl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) (),-    --     getCounter5Impl :: forall e'. String -> Eff (e' :& e) Int+    --   { incCounter5Impl :: 'Bluefin.Eff.Eff' e (),+    --     getCounter5Impl :: String -> Eff e Int     --   }+    --   deriving (Generic)+    --   deriving (Handle) via 'OneWayCoercibleHandle' Counter5     ---    -- instance 'Handle' Counter5 where-    --   mapHandle c =-    --     MkCounter5-    --       { incCounter5Impl = 'useImplUnder' (incCounter5Impl c),-    --         getCounter5Impl = \\msg -> useImplUnder (getCounter5Impl c msg)-    --       }+    -- instance (e \<: es) => 'OneWayCoercible.OneWayCoercible' (Counter5 e) (Counter5 es) where+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'     ---    -- incCounter5 :: (e :> es) => Counter5 e -> Eff es ()-    -- incCounter5 e = 'makeOp' (incCounter5Impl ('mapHandle' e))+    -- incCounter5 :: (e \<: es) => Counter5 e -> Eff es ()+    -- incCounter5 e = incCounter5Impl ('mapHandle' e)     ---    -- getCounter5 :: (e :> es) => Counter5 e -> String -> Eff es Int-    -- getCounter5 e msg = makeOp (getCounter5Impl (mapHandle e) msg)+    -- getCounter5 :: (e \<: es) => Counter5 e -> String -> Eff es Int+    -- getCounter5 e msg = getCounter5Impl (mapHandle e) msg     --     -- runCounter5 ::-    --   (e1 :> es) =>+    --   (e1 \<: es) =>     --   Stream String e1 ->     --   (forall e. Counter5 e -> Eff (e :& es) r) ->     --   Eff es Int     -- runCounter5 y k =-    --   'Bluefin.State.evalState' 0 $ \\st -> do-    --     _ \<- 'Bluefin.Exception.try' $ \\ex -> do+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do+    --     _ \<- 'Bluefin.Capability.Throw.try' $ \\ex -> do     --       'useImplIn'     --         k     --         ( MkCounter5     --             { incCounter5Impl = do-    --                 count <- 'Bluefin.State.get' st+    --                 count <- 'Bluefin.Capability.Modify.get' st     --     --                 when (even count) $     --                   'Bluefin.Stream.yield' y "Count was even"     --     --                 when (count >= 10) $-    --                   'Bluefin.Exception.throw' ex ()+    --                   'Bluefin.Capability.Throw.throw' ex ()     ---    --                 'Bluefin.State.put' st (count + 1),+    --                 'Bluefin.Capability.Modify.put' st (count + 1),     --               getCounter5Impl = \\msg -> do     --                 yield y msg     --                 get st@@ -324,52 +322,49 @@     -- | We can also freely combine concrete and dynamic effects.  In     -- the following example, the @incCounter6@ effect is left     -- dynamic, and defined in the handler, whilst @getCounter6@ is-    -- implemented in terms of concrete 'Bluefin.State.State' and 'Bluefin.Stream.Stream' effects.+    -- implemented in terms of concrete 'Bluefin.Capability.Modify.Modify' and 'Bluefin.Stream.Stream' effects.     --     -- @     -- data Counter6 e = MkCounter6-    --   { incCounter6Impl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) (),-    --     counter6State :: 'Bluefin.State.State' Int e,+    --   { incCounter6Impl :: 'Bluefin.Eff.Eff' e (),+    --     counter6State :: 'Bluefin.Capability.Modify.Modify' Int e,     --     counter6Stream :: 'Bluefin.Stream.Stream' String e     --   }+    --   deriving (Generic)+    --   deriving (Handle) via 'OneWayCoercibleHandle' Counter6     ---    -- instance 'Handle' Counter6 where-    --   mapHandle c =-    --     MkCounter6-    --       { incCounter6Impl = 'useImplUnder' (incCounter6Impl c),-    --         counter6State = 'mapHandle' (counter6State c),-    --         counter6Stream = mapHandle (counter6Stream c)-    --       }+    -- instance (e \<: es) => 'OneWayCoercible.OneWayCoercible' (Counter6 e) (Counter6 es) where+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'     ---    -- incCounter6 :: (e :> es) => Counter6 e -> Eff es ()-    -- incCounter6 e = 'makeOp' (incCounter6Impl (mapHandle e))+    -- incCounter6 :: (e \<: es) => Counter6 e -> Eff es ()+    -- incCounter6 e = incCounter6Impl (mapHandle e)     ---    -- getCounter6 :: (e :> es) => Counter6 e -> String -> Eff es Int+    -- getCounter6 :: (e \<: es) => Counter6 e -> String -> Eff es Int     -- getCounter6 (MkCounter6 _ st y) msg = do     --   yield y msg     --   get st     --     -- runCounter6 ::-    --   (e1 :> es) =>+    --   (e1 \<: es) =>     --   Stream String e1 ->     --   (forall e. Counter6 e -> Eff (e :& es) r) ->     --   Eff es Int     -- runCounter6 y k =-    --   'Bluefin.State.evalState' 0 $ \\st -> do-    --     _ \<- 'Bluefin.Exception.try' $ \\ex -> do+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do+    --     _ \<- 'Bluefin.Capability.Throw.try' $ \\ex -> do     --       'useImplIn'     --         k     --         ( MkCounter6     --             { incCounter6Impl = do-    --                 count <- 'Bluefin.State.get' st+    --                 count <- 'Bluefin.Capability.Modify.get' st     --     --                 when (even count) $     --                   'Bluefin.Stream.yield' y "Count was even"     --     --                 when (count >= 10) $-    --                   'Bluefin.Exception.throw' ex ()+    --                   'Bluefin.Capability.Throw.throw' ex ()     ---    --                 'Bluefin.State.put' st (count + 1),+    --                 'Bluefin.Capability.Modify.put' st (count + 1),     --               counter6State = mapHandle st,     --               counter6Stream = mapHandle y     --             }@@ -397,19 +392,24 @@      -- ** Dynamic effects with handles as arguments -    -- | We can implement dynamic effects that themselves take handles-    -- as arguments, by giving all the handle arguments the effect tag+    -- | We can implement dynamic effects that themselves take capabilities+    -- as arguments, by giving all the capability arguments the effect tag     -- @e'@.     --     -- @     -- data Counter7 e = MkCounter7-    --   { incCounter7Impl :: forall e'. 'Bluefin.Exception.Exception' () e' -> 'Bluefin.Eff.Eff' (e' :& e) (),-    --     counter7State :: 'Bluefin.State.State' Int e,+    --   { incCounter7Impl :: forall e'. 'Bluefin.Capability.Throw.Throw' () e' -> 'Bluefin.Eff.Eff' (e' :& e) (),+    --     counter7State :: 'Bluefin.Capability.Modify.Modify' Int e,     --     counter7Stream :: 'Bluefin.Stream.Stream' String e     --   }+    --   deriving (Handle) via OneWayCoercibleHandle Counter7     ---    -- instance 'Handle' Counter7 where-    --   mapHandle c =+    -- -- | The "forall" in the type of @incCounter7@ means that we+    -- -- can't derive the @OneWayCoercible@ instance with+    -- -- 'OneWayCoercible.gOneWayCoercible' so instead we use 'oneWayCoercibleTrustMe'.+    --+    -- instance (e \<: es) => 'OneWayCoercible' (Counter7 e) (Counter7 es) where+    --   oneWayCoercibleImpl = oneWayCoercibleTrustMe $ \\c ->     --     MkCounter7     --       { incCounter7Impl = \\ex -> 'useImplUnder' (incCounter7Impl c ex),     --         counter7State = 'mapHandle' (counter7State c),@@ -417,35 +417,35 @@     --       }     --     -- incCounter7 ::-    --   (e :> es, e1 :> es) => Counter7 e -> Exception () e1 -> Eff es ()+    --   (e \<: es, e1 \<: es) => Counter7 e -> Throw () e1 -> Eff es ()     -- incCounter7 e ex = 'makeOp' (incCounter7Impl ('mapHandle' e) (mapHandle ex))     ---    -- getCounter7 :: (e :> es) => Counter7 e -> String -> Eff es Int+    -- getCounter7 :: (e \<: es) => Counter7 e -> String -> Eff es Int     -- getCounter7 (MkCounter7 _ st y) msg = do     --   yield y msg     --   get st     --     -- runCounter7 ::-    --   (e1 :> es) =>+    --   (e1 \<: es) =>     --   Stream String e1 ->     --   (forall e. Counter7 e -> Eff (e :& es) r) ->     --   Eff es Int     -- runCounter7 y k =-    --   'Bluefin.State.evalState' 0 $ \\st -> do+    --   'Bluefin.Capability.Modify.evalModify' 0 $ \\st -> do     --     _ \<-     --       'useImplIn'     --         k     --         ( MkCounter7     --             { incCounter7Impl = \\ex -> do-    --                 count \<- 'Bluefin.State.get' st+    --                 count \<- 'Bluefin.Capability.Modify.get' st     --     --                 when (even count) $     --                   'Bluefin.Stream.yield' y "Count was even"     --     --                 when (count >= 10) $-    --                   'Bluefin.Exception.throw' ex ()+    --                   'Bluefin.Capability.Throw.throw' ex ()     ---    --                 'Bluefin.State.put' st (count + 1),+    --                 'Bluefin.Capability.Modify.put' st (count + 1),     --               counter7State = mapHandle st,     --               counter7Stream = mapHandle y     --             }@@ -494,25 +494,33 @@     --     -- @     -- data DynamicReader r e = DynamicReader-    --   { askLRImpl :: forall e'. 'Bluefin.Eff.Eff' (e' :& e) r,+    --   { askLRImpl :: 'Bluefin.Eff.Eff' e r,     --     localLRImpl :: forall e' a. (r -> r) -> Eff e' a -> Eff (e' :& e) a     --   }+    --   deriving (Handle) via OneWayCoercibleHandle (DynamicReader r)     ---    -- instance 'Handle' (DynamicReader r) where-    --   mapHandle h =+    -- -- | The "forall" in the type of @localRImpl@ means that we+    -- -- can't derive the @OneWayCoercible@ instance with+    -- -- 'OneWayCoercible.gOneWayCoercible' instead we use 'oneWayCoercibleTrustMe'.+    --+    -- instance+    --   (e \<: es) =>+    --   OneWayCoercible (DynamicReader r e) (DynamicReader r es)+    --   where+    --   oneWayCoercibleImpl = oneWayCoercibleTrustMe $ \\h ->     --     DynamicReader-    --       { askLRImpl = 'useImplUnder' (askLRImpl h),+    --       { askLRImpl = 'useImpl' (askLRImpl h),     --         localLRImpl = \\f k -> useImplUnder (localLRImpl h f k)     --       }     --     -- askLR ::-    --   (e :> es) =>+    --   (e \<: es) =>     --   DynamicReader r e ->     --   Eff es r     -- askLR c = 'makeOp' (askLRImpl ('mapHandle' c))     --     -- localLR ::-    --   (e :> es) =>+    --   (e \<: es) =>     --   DynamicReader r e ->     --   (r -> r) ->     --   Eff es a ->@@ -543,22 +551,21 @@     --     -- @     -- data FileSystem es = MkFileSystem-    --   { readFileImpl :: forall e. FilePath -> 'Bluefin.Eff.Eff' (e :& es) String,-    --     writeFileImpl :: forall e. FilePath -> String -> Eff (e :& es) ()+    --   { readFileImpl :: FilePath -> 'Bluefin.Eff.Eff' es String,+    --     writeFileImpl :: FilePath -> String -> Eff es ()     --   }+    --   deriving (Generic)+    --   deriving (Handle) via 'OneWayCoercibleHandle' FileSystem     ---    -- instance 'Handle' FileSystem where-    --   mapHandle fs = MkFileSystem {-    --     readFileImpl = \\fp -> 'useImplUnder' (readFileImpl fs fp),-    --     writeFileImpl = \\fp s -> useImplUnder (writeFileImpl fs fp s)-    --     }+    -- instance (e \<: es) => 'OneWayCoercible.OneWayCoercible' (FileSystem e) (FileSystem es) where+    --   oneWayCoercibleImpl = 'OneWayCoercible.gOneWayCoercible'     ---    -- readFile :: (e :> es) => FileSystem e -> FilePath -> Eff es String-    -- readFile fs filepath = 'makeOp' (readFileImpl ('mapHandle' fs) filepath)+    -- readFile :: (e \<: es) => FileSystem e -> FilePath -> Eff es String+    -- readFile fs filepath = readFileImpl ('mapHandle' fs) filepath     ---    -- writeFile :: (e :> es) => FileSystem e -> FilePath -> String -> Eff es ()+    -- writeFile :: (e \<: es) => FileSystem e -> FilePath -> String -> Eff es ()     -- writeFile fs filepath contents =-    --   makeOp (writeFileImpl (mapHandle fs) filepath contents)+    --   writeFileImpl (mapHandle fs) filepath contents     -- @     --     -- We can make a pure handler that simulates reading and writing@@ -567,24 +574,24 @@     --     -- @     -- runFileSystemPure ::-    --   (e1 :> es) =>-    --   Exception String e1 ->+    --   (e1 \<: es) =>+    --   Throw String e1 ->     --   [(FilePath, String)] ->     --   (forall e2. FileSystem e2 -> Eff (e2 :& es) r) ->     --   Eff es r     -- runFileSystemPure ex fs0 k =-    --   'Bluefin.State.evalState' fs0 $ \\fs ->+    --   'Bluefin.Capability.Modify.evalModify' fs0 $ \\fs ->     --     'useImplIn'     --       k     --       MkFileSystem     --         { readFileImpl = \\filepath -> do-    --             fs' <- 'Bluefin.State.get' fs+    --             fs' <- 'Bluefin.Capability.Modify.get' fs     --             case lookup filepath fs' of     --               Nothing ->-    --                 'Bluefin.Exception.throw' ex ("File not found: " <> filepath)+    --                 'Bluefin.Capability.Throw.throw' ex ("File not found: " <> filepath)     --               Just s -> pure s,     --           writeFileImpl = \\filepath contents ->-    --             'Bluefin.State.modify' fs ((filepath, contents) :)+    --             'Bluefin.Capability.Modify.modify' fs ((filepath, contents) :)     --         }     -- @     --@@ -594,8 +601,8 @@     -- @     -- runFileSystemIO ::     --   forall e1 e2 es r.-    --   (e1 :> es, e2 :> es) =>-    --   Exception String e1 ->+    --   (e1 \<: es, e2 \<: es) =>+    --   Throw String e1 ->     --   IOE e2 ->     --   (forall e. FileSystem e -> Eff (e :& es) r) ->     --   Eff es r@@ -609,10 +616,10 @@     --           \\filepath -> adapt . Prelude.writeFile filepath     --       }     --   where-    --     adapt :: (e1 :> ess, e2 :> ess) => IO a -> Eff ess a+    --     adapt :: (e1 \<: ess, e2 \<: ess) => IO a -> Eff ess a     --     adapt m =     --       effIO io (Control.Exception.try @IOException m) >>= \\case-    --         Left e -> 'Bluefin.Exception.throw' ex (show e)+    --         Left e -> 'Bluefin.Capability.Throw.throw' ex (show e)     --         Right r -> pure r     -- @     --@@ -620,7 +627,7 @@     -- does some file system operations.     --     -- @-    -- action :: (e :> es) => FileSystem e -> Eff es String+    -- action :: (e \<: es) => FileSystem e -> Eff es String     -- action fs = do     --   file <- readFile fs "\/dev\/null"     --   when (length file == 0) $ do@@ -632,7 +639,7 @@     --     -- @     -- exampleRunFileSystemPure :: Either String String-    -- exampleRunFileSystemPure = 'Bluefin.Eff.runPureEff' $ 'Bluefin.Exception.try' $ \\ex ->+    -- exampleRunFileSystemPure = 'Bluefin.Eff.runPureEff' $ 'Bluefin.Capability.Throw.try' $ \\ex ->     --   runFileSystemPure ex [("\/dev\/null", "")] action     -- @     --@@ -645,7 +652,7 @@     --     -- @     -- exampleRunFileSystemIO :: IO (Either String String)-    -- exampleRunFileSystemIO = 'Bluefin.Eff.runEff_' $ \\io -> try $ \\ex ->+    -- exampleRunFileSystemIO = 'Bluefin.Eff.runEff' $ \\io -> try $ \\ex ->     --   runFileSystemIO ex io action     -- @     --@@ -657,7 +664,26 @@     -- @      -- * Functions for making compound effects-    Handle (mapHandle),++    -- ** @Handle@+    Handle (handleImpl),+    HandleD,+    mapHandle,++    -- ** @OneWayCoercible@++    -- | The documentation for 'Handle' shows how to use+    -- @OneWayCoercible@ to define @Handle@ instances.+    OneWayCoercible.OneWayCoercible (OneWayCoercible.oneWayCoercibleImpl),+    OneWayCoercibleHandle (MkOneWayCoercibleHandle),+    handleOneWayCoercible,+    withHandle,+    OneWayCoercible.gOneWayCoercible,+    oneWayCoercibleTrustMe,+    -- | Bluefin re-exports @Generic@ for convenience.+    OneWayCoercible.Generic,++    -- ** Other functions for compound effects     makeOp,     useImpl,     useImplUnder,@@ -674,3 +700,4 @@ where  import Bluefin.Internal+import qualified Bluefin.Internal.OneWayCoercible as OneWayCoercible
src/Bluefin/Consume.hs view
@@ -1,14 +1,21 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.Await" instead. module Bluefin.Consume   ( -- | 'Consume' allows you to await values during the execution of     -- a Bluefin operation.  It provides similar functionality to     -- @await@ from Conduit or Pipes.+    --+    -- For information about prompt finalization/resource safety when+    -- using Bluefin @Consume@s, see "Bluefin.Coroutine".      -- * Handle     Consume,+     -- * Handlers     consumeEach,     consumeStream,     streamConsume,+     -- * Effectful operations     await,     takeConsume,
src/Bluefin/Coroutine.hs view
@@ -1,11 +1,28 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.Request"+-- instead. module Bluefin.Coroutine   ( -- | @Coroutine@ allows to yield values and receive results back.     -- [Wikipedia     -- suggests](https://en.wikipedia.org/wiki/Coroutine#Definition_and_types)     -- that Bluefin's coroutines are "second-class stackful-    -- coroutines".  This module is not documented yet.  You might+    -- coroutines".  This module is not documented much yet.  You might     -- want to start with "Bluefin.Stream", which is the most common     -- way to use coroutines.++    -- ** Prompt finalization/resource safety++    -- | Bluefin+    -- 'Bluefin.Stream.Stream'\/'Bluefin.Consume.Consume'\/'Bluefin.Coroutine.Coroutine'+    -- computations have much better resource safety properties than+    -- Conduit and Pipes.  You can use+    -- @Bluefin.Eff.'Bluefin.Eff.bracket'@ within a streaming+    -- computation and the acquired resource is guaranteed to be+    -- released and the end of the bracket, rather than at the end of+    -- the @ResourceT@ scope as it is the case in Conduit and Pipes.+    -- See the blog post [Bluefin streams finalize+    -- promptly](https://h2.jaguarpaw.co.uk/posts/bluefin-streams-finalize-promptly/)+    -- for more details.      -- * Handle     Coroutine,
+ src/Bluefin/DslBuilder.hs view
@@ -0,0 +1,341 @@+module Bluefin.DslBuilder+  ( -- | Haksell is great for writing domain specific languages (DSLs)+    -- and @Bluefin.DslBuilder@ provides an easy way to write DSLs+    -- using Bluefin.++    -- * Robot arena example++    -- ** Data types for the robot arena++    -- | Here's an example of the use of @Bluefin.DslBuilder@. Suppose+    -- we have a data type that represents the location of robots and+    -- obstacles in a two-dimensional square arena:+    --+    -- @+    -- data Arena = MkArena+    --  { arenaRobots :: [RobotEntry],+    --    arenaObstacles :: [ObstacleEntry]+    --  }+    -- @+    --+    -- Each @RobotEntry@ stores the robot's name, coordinates on the+    -- 2d grid, facing direction, and instructions for robot to carry+    -- out+    --+    -- @+    -- type RobotEntry = (String, (Int, Int), Direction, [Instruction])+    -- @+    --+    -- The instructions that a robot can perform are to wait for a+    -- given number of time units, move forward, turn left and turn+    -- right.+    --+    -- @+    -- data Instruction = Wait Int | Forward | TurnLeft | TurnRight+    -- data Direction = N | E | S | W+    -- @+    --+    -- The @ObstacleEntry@s store the type of each obstacle and its+    -- coordinates on the 2d grid.+    --+    -- @+    -- type ObstacleEntry = (Obstacle, (Int, Int))+    --+    -- data Obstacle = Sand | Rock | Iron+    -- @++    -- ** Defining an @Arena@ by hand++    -- | Suppose we want an @Arena@ with a red robot which moves+    -- towards a sand obstacle, and a blue robot that is stuck behind+    -- iron obstacles and can only turn around on the spot. Here's an+    -- ASCII diagram of the initial position we want, where @r@ is the+    -- red robot, @S@ is a sand obstacle, @b@ is the blue robot and+    -- @I@ is an iron obstacle:+    --+    -- @+    -- 5|+    -- 4|  III+    -- 3|  IbI+    -- 2|  III+    -- 1|+    -- 0|r    S+    --  +------+    --   012345+    -- @+    --+    -- We can define such an @Arena@ by hand like this:+    --+    -- @+    -- myArena :: Arena+    -- myArena =+    --   MkArena+    --     { arenaRobots =+    --         [ ("red", (0, 0), E, [Wait 100, Forward, Forward, Forward, Forward]),+    --           ("blue", (3, 3), N, [TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight, TurnRight])+    --         ],+    --       arenaObstacles = [(Sand, (5, 0)), (Iron, (2, 2)), (Iron, (2, 3)), (Iron, (2, 4)), (Iron, (3, 2)), (Iron, (3, 4)), (Iron, (4, 2)), (Iron, (4, 3)), (Iron, (4, 4))]+    --     }+    -- @+    --+    -- That's messy and contains a lot of repetition!  We can use+    -- Haskell constructs to do a bit better:+    --+    -- @+    -- myArena2 :: Arena+    -- myArena2 =+    --   MkArena+    --     { arenaRobots =+    --         [ ("red", (0, 0), E, Wait 100 : replicate 4 Forward),+    --           ("blue", (3, 3), N, replicate 20 TurnRight)+    --         ],+    --       arenaObstacles =+    --         (Sand, (5, 0))+    --           : [ (Iron, (x, y))+    --               | x <- [2 .. 4],+    --                 y <- [2 .. 4],+    --                 (x, y) /= (3, 3)+    --             ]+    --     }+    -- @+    --+    -- That's more compressed but it doesn't describe our intent+    -- clearly.++    -- ** Defining an @Arena@ with a DSL++    -- | Let's use @Bluefin.DslBuilder@ to write a DSL that allows us+    -- to express our intent more clearly.  Before we define the DSL,+    -- let's look at what it will allow us to write.  In @myDslArena@+    -- below I can define the red robot and its obstacles separately+    -- from the blue robot and its obstacles, and I can use `for_`+    -- loops to conveniently define the blue robot's iron cage.+    --+    -- @+    -- myDslArena :: Arena+    -- myDslArena = buildArena $ do+    --   -- 5|+    --   -- 4|+    --   -- 3|+    --   -- 2|+    --   -- 1|+    --   -- 0|R    S+    --   --  +------+    --   --   012345+    --   robot "red" (0, 0) E $ do+    --     wait 100+    --     forward 4+    --+    --   obstacle Sand (5, 0)+    --+    --   -- 5|+    --   -- 4|  III+    --   -- 3|  IBI+    --   -- 2|  III+    --   -- 1|+    --   -- 0|+    --   --  +------+    --   --   012345+    --   robot "blue" (3, 3) N $ do+    --     replicateM_ 10 aboutFace+    --+    --   for_ [2 .. 4] $ \\x -> do+    --     for_ [2 .. 4] $ \\y -> do+    --       unless ((x, y) == (3, 3)) $ do+    --         obstacle Iron (x, y)+    -- @++    -- ** Arena DSL definitions++    -- | So what are the definitions of the components that go into+    -- building an @Arena@?++    -- *** @buildArena@ and @ArenaBuilder@++    -- | Firstly, what does @buildArena@ do?  It's going to have this+    -- type:+    --+    -- @+    -- buildArena :: ArenaBuilder -> Arena+    -- @+    --+    -- @ArenaBuilder@ is the type of the @do@ block which contains the+    -- @robot@ and @obstacle@ entries, and is a convenience type+    -- synonym:+    --+    -- @+    -- type ArenaBuilder = ArenaBuilder_ ()+    -- @+    --+    -- @ArenaBuilder_@ is a @Monad@ and is the first component+    -- we are going to build using @Bluefin.DslBuilder@:+    --+    -- @+    -- newtype ArenaBuilder_ r+    --   = MkArenaBuilder ('DslBuilder' ArenaH r)+    --   deriving (Functor, Applicative, Monad)+    -- @+    --+    -- @DslBuilder ArenaH@ is a @Monad@ that allows us access to the+    -- effects inside the capability @ArenaH@ (and no others).  So what is+    -- @ArenaH@? It is defined like this:+    --+    -- @+    -- data ArenaH e = MkArenaH ('Bluefin.Stream.Stream' RobotEntry e) (Stream ObstacleEntry e)+    --   deriving t'Bluefin.Compound.Generic'+    --   deriving t'Bluefin.Compound.Handle' via t'Bluefin.Compound.OneWayCoercibleHandle' ArenaH+    --+    -- instance (e \<: es) => 'Bluefin.Compound.OneWayCoercible' (ArenaH e) (ArenaH es) where+    --   'Bluefin.Compound.oneWayCoercibleImpl' = 'Bluefin.Compound.gOneWayCoercible'+    -- @+    --+    -- What does that mean? Well, @ArenaH@ is defined according to one+    -- of the recipes from "Bluefin.Compound", and gives the ability+    -- to yield to a @Stream@ of @RobotEntry@s and a stream of+    -- @ObstacleEntry@s, i.e. the components that make up an @Arena@.+    -- The only things we can do with the @ArenaH@ then are to give it+    -- @RobotEntry@s or @ObstacleEntry@s.  How do we get them?++    -- *** @obstacle@++    -- | To get an @ObstacleEntry@ we use the @obstacle@ command.+    -- It has type+    --+    -- @+    -- obstacle :: Strength -> (Int, Int) -> ArenaBuilder+    -- @+    --+    -- When calling @obstacle@ we specify the strength of the obstacle+    -- and its coordinates in the arena.  In fact, having those gives+    -- us exactly what we need to yield an @ObstacleEntry@ to the+    -- @Stream ObstacleEntry@ inside the @ArenaBuilder@:+    --+    -- @+    -- obstacle o coord =+    --   MkArenaBuilder $ 'dslBuilder' $ \(MkArenaH _ yobstacle) -> do+    --     'Bluefin.Stream.yield' yobstacle (o, coord)+    -- @++    -- *** @robot@ and @InstructionsBuilder@++    -- | To get a @RobotEntry@ we use the @robot@ component. It has+    -- type+    --+    -- @+    -- robot ::+    --   String -> (Int, Int) -> Direction -> InstructionsBuilder -> ArenaBuilder+    -- @+    --+    -- When calling @robot@ we specify the name, coordinates, and+    -- facing direction for our robot.  We also specify the+    -- instructions for the robot by providing an+    -- @InstructionsBuilder@? What's that?  It's /another/ @Monad@+    -- defined in terms of @DslBuilder@:+    --+    -- @+    -- type InstructionsBuilder = InstructionsBuilder_ ()+    --+    -- newtype InstructionsBuilder_ r+    --   = MkInstructionsBuilder ('DslBuilder' InstructionsH r)+    --   deriving (Functor, Applicative, Monad)+    -- @+    --+    -- Like with @ArenaBuilder@, to define the @Monad@ we define a+    -- capability, this time @InstructionsH@:+    --+    -- @+    -- data InstructionsH e = MkInstructionsH ('Bluefin.Stream.Stream' Instruction e)+    --   deriving t'Bluefin.Compound.Generic'+    --   deriving t'Bluefin.Compound.Handle' via t'Bluefin.Compound.OneWayCoercibleHandle' InstructionsH+    --+    -- instance (e \<: es) => t'Bluefin.Compound.OneWayCoercible' (InstructionsH e) (InstructionsH es) where+    --   oneWayCoercibleImpl = 'Bluefin.Compound.gOneWayCoercible'+    -- @+    --+    -- @InstructionsH@ allows us to yield to a sequence of+    -- @Instruction@s, i.e. the type of robot instructions defined+    -- above and used in @Arena@ via @RobotEntry@.  In fact, the job+    -- of @robot@ is exactly to allow us to define a @RobotEntry@ and+    -- yield it to the @Stream RobotEntry@ of @Arena@:+    --+    -- @+    -- robot name coords dir (MkInstructionsBuilder ibuilder) =+    --   MkArenaBuilder $ 'dslBuilder' $ \\(MkArenaH yrobot _) -> do+    --     (insns, ()) \<- 'Bluefin.Stream.yieldToList' $ \\yinsns -> do+    --       'runDslBuilder' (MkInstructionsH ('Bluefin.Compound.mapHandle' yinsns)) ibuilder+    --+    --     'Bluefin.Stream.yield' yrobot (name, coords, dir, insns)+    -- @++    -- *** Creating @InstructionsBuilder@s++    -- | In a @do@ block of type @InstructionsBuilder@ we want to be+    -- able to write things like @wait 100@, @forward 4@ and+    -- @aboutFace@.  What are they?  To define commands of type+    -- @InstructionsBuilder@ we use this convenience function:+    --+    -- @+    -- instructionsBuilder :: Instruction -> InstructionsBuilder+    -- instructionsBuilder insn =+    --   MkInstructionsBuilder $ dslBuilder $ \\(MkInstructionsH yinsn) -> do+    --     yield yinsn insn+    -- @+    --+    -- which we can use as follows to define commands as follows:+    --+    -- @+    -- wait :: Int -> InstructionsBuilder+    -- wait n = instructionsBuilder (Wait n)+    --+    -- turnLeft :: InstructionsBuilder+    -- turnLeft = instructionsBuilder TurnLeft+    --+    -- turnRight :: InstructionsBuilder+    -- turnRight = instructionsBuilder TurnRight+    --+    -- aboutFace :: InstructionsBuilder+    -- aboutFace = do+    --   turnRight+    --   turnRight+    --+    -- forward :: Int -> InstructionsBuilder+    -- forward n = replicateM_ n (instructionsBuilder Forward)+    -- @++    -- *** Implementing @buildArena@++    -- | We're now ready to implement @buildArena@. We create a+    -- @Stream RobotEntry@ and a @Stream ObstacleEntry@ to pass to the+    -- @MkArenaH@ constructor, and use @runDslBuilder@ to run the+    -- @ArenaBuilder@ provided.  (This is a lot like some of the approaches+    -- in "Bluefin.Compound".)+    --+    -- @+    -- buildArena :: ArenaBuilder -> Arena+    -- buildArena (MkArenaBuilder arenaBuilder) = runPureEff $ do+    --   (robots, obstacles) \<- 'Bluefin.Stream.yieldToList' $ \\yrobots -> do+    --     (obstacles, ()) \<- yieldToList $ \\yobstacles -> do+    --       'runDslBuilder'+    --         (MkArenaH ('Bluefin.Compound.mapHandle' yrobots) (mapHandle yobstacles))+    --         arenaBuilder+    --+    --     pure obstacles+    --+    --   pure+    --     MkArena+    --       { arenaRobots = robots,+    --         arenaObstacles = obstacles+    --       }+    -- @+    --+    -- And that's all we need to support the implementation of+    -- @myDslArena :: Arena@ given above!++    -- * @DslBuilder@+    DslBuilder,+    dslBuilder,+    runDslBuilder,+  )+where++import Bluefin.Internal.DslBuilder
+ src/Bluefin/DslBuilderEff.hs view
@@ -0,0 +1,10 @@+-- | Like "Bluefin.DslBuilder", but when you want to be able to run+-- additional effects as well.+module Bluefin.DslBuilderEff+  ( DslBuilderEff,+    dslBuilderEff,+    runDslBuilderEff,+  )+where++import Bluefin.Internal.DslBuilderEff
src/Bluefin/EarlyReturn.hs view
@@ -1,3 +1,6 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.ReturnEarly"+-- instead. module Bluefin.EarlyReturn   ( -- | Early return allows to define a block from which you can     -- return early.  Early return is implemented as an exception, and@@ -5,8 +8,10 @@      -- * Handle     EarlyReturn,+     -- * Handlers     withEarlyReturn,+     -- * Effectful operations     returnEarly,   )
src/Bluefin/Eff.hs view
@@ -1,24 +1,33 @@+{-# LANGUAGE ExplicitNamespaces #-}+ module Bluefin.Eff   ( -- * 'Eff' monad     Eff,+     -- * Run an 'Eff'     runPureEff,-    runEff_,     runEff,+     -- * Resource management     bracket,+    finally,+     -- * Type classes      -- | See "Bluefin.Eff.IO" for the most direct way of doing I/O in     -- Bluefin.  If you really want to use 'MonadIO' you can use     -- 'withMonadIO'.-     withMonadIO,     withMonadFail,+     -- * Effect tracking     Effects,     (:>),+    type (<:),     (:&),++    -- * Deprecated+    runEff_,   ) where 
src/Bluefin/Exception.hs view
@@ -1,10 +1,15 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.Throw"+-- instead. module Bluefin.Exception   ( -- * Handle     Exception,+     -- * Handlers     try,     handle,     catch,+     -- * Effectful operations     throw,     rethrowIO,
+ src/Bluefin/Exception/GeneralBracket.hs view
@@ -0,0 +1,19 @@+module Bluefin.Exception.GeneralBracket+  ( -- * Effectful functions+    generalBracket,++    -- * Handle+    MakeExceptions,+    catchWithResource,+    pureMakeExceptions,+    apMakeExceptions,+    fmapMakeExceptions,++    -- * @:~>@+    (:~>),+    abstract,+  )+where++import Bluefin.Internal.CloneableHandle+import Bluefin.Internal.Exception
+ src/Bluefin/GadtEffect.hs view
@@ -0,0 +1,251 @@+module Bluefin.GadtEffect+  ( -- * Introduction++    -- | The Haskell effect systems @effectful@ and @polysemy@ allow+    -- users to define new effects by defining a GADT (generalized+    -- algebraic data type) whose contructors correspond to primitive+    -- operations of the effect, and then creating values of the GADT+    -- and interpreting them in terms of existing effects.  This+    -- module provides Bluefin's equivalent.  In fact, in @effectful@+    -- and @polysemy@ this is essentially the /only/ way you can+    -- create new effects. That's not true for Bluefin. Bluefin+    -- supports a rich collection of ways to create new effects, most+    -- of which are documented at "Bluefin.Compound".  This particular+    -- module might be helpful for users coming from @effectful@ and+    -- @polysemy@, however.++    -- * Example filesystem effect++    -- | First we define a GADT with a constructor for each primitive+    -- operation of the effect we want to define.  Here the primitive+    -- operations are to read a file, write a file and to wrap an+    -- effectful computation in a "trace" block.+    --+    -- @+    -- data FileSystem :: 'Effect' where+    --   ReadFile :: FilePath -> FileSystem m String+    --   WriteFile :: FilePath -> String -> FileSystem m ()+    --   Trace :: String -> m r -> FileSystem m r+    -- @+    --+    -- Then we need to define two instances for @FileSystem@:+    --+    -- @+    -- instance+    --   (e \<: es) =>+    --   t'Bluefin.Compound.OneWayCoercible' ('GadtEffect' FileSystem r e) (GadtEffect FileSystem r es)+    --   where+    --   'Bluefin.Compound.oneWayCoercibleImpl' = 'oneWayCoercibleGadtEffectTrustMe' $ \\case+    --     ReadFile path -> ReadFile path+    --     WriteFile path contents -> WriteFile path contents+    --     Trace msg body -> Trace msg (useImpl body)+    --+    -- deriving via+    --   t'Bluefin.Compound.OneWayCoercibleHandle' ('GadtEffect' FileSystem r)+    --   instance+    --     t'Bluefin.Compound.Handle' (GadtEffect FileSystem r)+    -- @+    --+    -- Then we can define functions that implement the primitive+    -- effectful operations for @FileSystem@:+    --+    -- @+    -- readFile ::+    --   (e1 \<: es) =>+    --   'Send' FileSystem e1 ->+    --   FilePath ->+    --   Eff es String+    -- readFile fc path =+    --   'send' fc (ReadFile path)+    --+    -- writeFile ::+    --   (e1 \<: es) =>+    --   Send FileSystem e1 ->+    --   FilePath ->+    --   String ->+    --   Eff es ()+    -- writeFile fc path content =+    --   send fc (WriteFile path content)+    --+    -- trace ::+    --   (e1 \<: es) =>+    --   Send FileSystem e1 ->+    --   String ->+    --   Eff es r ->+    --   Eff es r+    -- trace fc msg body =+    --   send fc (Trace msg body)+    -- @+    --+    -- The instances and primitive effectful operations are+    -- boilerplate.  @effectful@ and @polysemy@ have Template Haskell+    -- for generating their boilerplate+    -- ([@makeEffect@](https://hackage.haskell.org/package/effectful-th/docs/Effectful-TH.html#v:makeEffect)+    -- and+    -- [@makeSem@](https://hackage.haskell.org/package/polysemy-1.9.2.0/docs/Polysemy.html#v:makeSem)+    -- respectively) but there is no such thing for Bluefin yet,+    -- sorry!  Please [open an+    -- issue](https://github.com/tomjaguarpaw/bluefin/issues/new) if+    -- that causes difficulties for you.+    --+    -- Finally we can write a handler for the @'Send' FileSystem@+    -- effect that gives it an interpretation via 'interpret':+    --+    -- @+    -- import System.IO qualified as IO+    --+    -- runFileSystem ::+    --   forall es e1 e2 r.+    --   (e1 \<: es, e2 \<: es) =>+    --   t'Bluefin.IO.IOE' e1 ->+    --   t'Bluefin.Exception.Exception' t'Control.Exception.IOException' e2 ->+    --   (forall e. 'Send' FileSystem e -> Eff (e :& es) r) ->+    --   Eff es r+    -- runFileSystem io ex = 'interpret' $ \\case+    --   ReadFile path ->+    --     adapt (IO.'System.IO.readFile' path)+    --   WriteFile path contents ->+    --     adapt (IO.'System.IO.writeFile' path contents)+    --   Trace msg body -> do+    --     'Bluefin.IO.effIO' io (putStrLn ("Start: " <> msg))+    --     r <- 'Bluefin.Compound.useImpl' body+    --     effIO io (putStrLn ("End: " <> msg))+    --     pure r+    --   where+    --     -- If you don't want to write this signature you can use+    --     -- {-# LANGUAGE NoMonoLocalBinds #-}+    --     adapt :: (e1 \<: es', e2 \<: es') => IO r' -> Eff es' r'+    --     adapt m = 'Bluefin.IO.rethrowIO' io ex (effIO io m)+    -- @++    -- * @interpose@ example++    -- | If you're familiar with @effectful@'s @interpose@ function+    -- you may want to use Bluefin's equivalent.  To see how, let's+    -- replicate [@effectful@'s interpose+    -- example](https://hackage-content.haskell.org/package/effectful-core-2.6.1.0/docs/Effectful-Dispatch-Dynamic.html#v:interpose). First+    -- we define a simple effect with three primitive operations:+    --+    -- @+    -- data E :: 'Effect' where+    --   Op1 :: E m ()+    --   Op2 :: E m ()+    --   Op3 :: E m ()+    -- @+    --+    -- Then we define the boilerplate instances+    --+    -- @+    -- instance+    --   (e \<: es) =>+    --   t'Bluefin.Compound.OneWayCoercible' ('GadtEffect' E r e) (GadtEffect E r es)+    --   where+    --   'Bluefin.Compound.oneWayCoercibleImpl' = 'oneWayCoercibleGadtEffectTrustMe' $ \\case+    --     Op1 -> Op1+    --     Op2 -> Op2+    --     Op3 -> Op3+    --+    -- deriving via+    --   t'Bluefin.Compound.OneWayCoercibleHandle' (GadtEffect E r)+    --   instance+    --     t'Bluefin.Compound.Handle' (GadtEffect E r)+    -- @+    --+    -- and a handler for the @'Send' E@ effect:+    --+    -- @+    -- runE ::+    --   (e1 \<: es) =>+    --   IOE e1 ->+    --   (forall e. Send E e -> Eff (e :& es) r) ->+    --   Eff es r+    -- runE io = interpret $ \\case+    --   Op1 -> effIO io (putStrLn "op1")+    --   Op2 -> effIO io (putStrLn "op2")+    --   Op3 -> effIO io (putStrLn "op3")+    -- @+    --+    -- Before using 'interpose', let's look at a use of its simpler+    -- cousin, 'interpret':+    --+    -- @+    -- augmentOp2Interpret ::+    --   (e1 \<: es, e2 \<: es) =>+    --   IOE e2 ->+    --   Send E e1 ->+    --   (forall e. Send E e -> Eff (e :& es) r) ->+    --   Eff es r+    -- augmentOp2Interpret io fc = 'interpret' $ \\case+    --   Op2 -> effIO io (putStrLn "augmented op2") >> send fc Op2+    --   op -> 'passthrough' fc op+    -- @+    --+    -- Using 'interpose' is similar:+    --+    -- @+    -- augmentOp2Interpose ::+    --   (e1 \<: es, e2 \<: es) =>+    --   IOE e2 ->+    --   t'Bluefin.HandleReader.HandleReader' (Send E) e1 ->+    --   Eff es r ->+    --   Eff es r+    -- augmentOp2Interpose io = 'interpose' $ \\fc -> \\case+    --   Op2 -> effIO io (putStrLn "augmented op2") >> send fc Op2+    --   op -> 'passthrough' fc op+    -- @+    --+    -- And now let's see what they each do:+    --+    -- @+    -- example :: IO ()+    -- example = runEff $ \\io -> do+    --   let action fc = do+    --         send fc Op1+    --         send fc Op2+    --         send fc Op3+    --+    --   effIO io (putStrLn "-- interpret:")+    --   runE io $ \\fc -> do+    --     augmentOp2Interpret io fc $ \\fc' -> action fc'+    --+    --   effIO io (putStrLn "-- interpose:")+    --   runE io $ \\fc -> 'Bluefin.HandleReader.runHandleReader' fc $ \\hr -> do+    --     augmentOp2Interpose io hr $ 'Bluefin.HandleReader.asksHandle' hr action+    -- @+    --+    -- @+    -- ghci> example+    -- -- interpret:+    -- op1+    -- augmented op2+    -- op2+    -- op3+    -- -- interpose:+    -- op1+    -- augmented op2+    -- op2+    -- op3+    -- @++    -- * Handle+    Send,++    -- * Effectful operations+    send,+    passthrough,++    -- * Interpretation+    EffectHandler,+    interpret,+    interpose,++    -- * @Effect@+    Effect,++    -- * @GadtEffect@+    GadtEffect,+    oneWayCoercibleGadtEffectTrustMe,+  )+where++import Bluefin.Internal.GadtEffect
src/Bluefin/HandleReader.hs view
@@ -1,12 +1,33 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use+-- "Bluefin.Capability.AskCapability" instead.+--+-- 'HandleReader' is like t'Bluefin.Reader.Reader', generalized to+-- work for arbitrary t'Bluefin.Compound.Handle's.  'localHandle'+-- locally overrides the value of a capability in a well-scoped way.  The+-- original capability will be restored when you exit the @localHandle@+-- block regardless of whether the exit was normal or via an+-- exception.+--+-- @HandleReader@ supports functionality similiar to @effectful@'s+-- [@interpose@](https://hackage.haskell.org/package/effectful-core/docs/Effectful-Dispatch-Dynamic.html#v:interpose)+-- and @polysemy@'s+-- [@intercept@](https://hackage.haskell.org/package/polysemy/docs/Polysemy.html#v:intercept),+-- that is, locally augmenting an effect with new behaviors.  If you+-- want to do the same in Bluefin you may want to start with+-- @Bluefin.GadtEffect.'Bluefin.GadtEffect.interpose`@. module Bluefin.HandleReader-  (-- * Handle-   HandleReader,-   -- * Handlers-   runHandleReader,-   -- * Effectful operations-   askHandle,-   localHandle,+  ( -- * Handle+    HandleReader,++    -- * Handlers+    runHandleReader,++    -- * Effectful operations+    askHandle,+    asksHandle,+    localHandle,   )-  where+where  import Bluefin.Internal
src/Bluefin/IO.hs view
@@ -1,24 +1,31 @@ module Bluefin.IO   ( -- | You can run 'IO' operations inside 'Eff'. -    -- * Handle+    -- * Capability     IOE,+     -- * Handlers-    runEff_,     runEff,+     -- * Effectful operations     effIO,     rethrowIO,+     -- * IO type classes     withMonadIO,     withEffToIO_,+    withEffToIOCloneHandle,+     -- ** @EffReader@     EffReader,     effReader,     runEffReader,+     -- ** Deprecated versions     withEffToIO,+    runEff_,   ) where  import Bluefin.Internal+import Bluefin.Internal.CloneableHandle
src/Bluefin/Jump.hs view
@@ -1,3 +1,5 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.Jump" instead. module Bluefin.Jump   ( -- | 'Jump' allows you to jump back to a previously-set location.     -- A "jump" is equivalent to an untyped early return, or more@@ -6,8 +8,10 @@      -- * Handle     Jump,+     -- * Handlers     withJump,+     -- * Effectful operations     jumpTo,   )
src/Bluefin/Pipes.hs view
@@ -1,14 +1,20 @@ -- | Reimplementation of the @pipes@ (@Pipes@) ecosystem in Bluefin.--- It primarily serves as an example of what you can do with Bluefin--- and you probably won't want to use it directly.  Instead you are--- recommended to use ----- * 'Bluefin.Stream', 'Bluefin.Stream.yield'--- * 'Bluefin.Consume', 'Bluefin.Consume.await'--- * 'Bluefin.Stream.consumeStream'--- * For advanced cases only, 'Bluefin.Coroutine',---   'Bluefin.Coroutine.yieldCoroutine' and---   'Bluefin.Coroutine.connectCoroutines'+-- You should not use this module.  It will be deprecated and removed+-- in future versions.+--+-- This module is just an example of what you can do with Bluefin and+-- as such it should be obtained from+-- [@bluefin-examples@](https://github.com/tomjaguarpaw/bluefin/tree/master/bluefin-examples)+-- if you want it.  Instead of using it directly you are recommended+-- to use+--+-- * t'Bluefin.Capability.Yield.Yield', 'Bluefin.Capability.Yield.yield'+-- * t'Bluefin.Capability.Await.Await', 'Bluefin.Capability.Await.await'+-- * 'Bluefin.Capability.Yield.awaitYield'+-- * For advanced cases only, t'Bluefin.Capability.Request.Request',+--   'Bluefin.Capability.Request.request' and+--   'Bluefin.Capability.Request.connectRequests' -- -- See also "Bluefin.Pipes.Prelude". module Bluefin.Pipes
src/Bluefin/Pipes/Prelude.hs view
@@ -1,19 +1,25 @@--- | Reimplementation of the @pipes@ prelude (@Pipes.Prelude@) in--- Bluefin.  It primarily serves as an example of what you can do with--- Bluefin and you probably won't want to use it directly.  Instead--- you are recommended to use+-- | Reimplementation of the @pipes@ (@Pipes@) ecosystem in Bluefin. ----- * 'Bluefin.Stream', 'Bluefin.Stream.yield'--- * 'Bluefin.Consume', 'Bluefin.Consume.await'--- * 'Bluefin.Stream.consumeStream'--- * For advanced cases only, 'Bluefin.Coroutine',---   'Bluefin.Coroutine.yieldCoroutine' and---   'Bluefin.Coroutine.connectCoroutines'+-- You should not use this module.  It will be deprecated and removed+-- in future versions. --+-- This module is just an example of what you can do with Bluefin and+-- as such it should be obtained from+-- [@bluefin-examples@](https://github.com/tomjaguarpaw/bluefin/tree/master/bluefin-examples)+-- if you want it.  Instead of using it directly you are recommended+-- to use+--+-- * t'Bluefin.Capability.Yield.Yield', 'Bluefin.Capability.Yield.yield'+-- * t'Bluefin.Capability.Await.Await', 'Bluefin.Capability.Await.await'+-- * 'Bluefin.Capability.Yield.awaitYield'+-- * For advanced cases only, t'Bluefin.Capability.Request.Request',+--   'Bluefin.Capability.Request.request' and+--   'Bluefin.Capability.Request.connectRequests'+-- -- See also "Bluefin.Pipes". -- -- @--- >>> 'Bluefin.Eff.runEff_' $ \\io -> 'runEffect' $ do+-- >>> 'Bluefin.Eff.runEff' $ \\io -> 'runEffect' $ do --       'stdinLn' io >-> 'takeWhile'' (/= "quit") >-> 'stdoutLn' io -- Test -- Test
+ src/Bluefin/Prim.hs view
@@ -0,0 +1,44 @@+-- | For defining @PrimMonad@ instances, for example:+--+-- @+-- -- Define a capability which includes Prim+-- data ExAndPrim e = MkExAndPrim (Exception String e) (P.Prim e)+--   -- Give it a Handle instance, as per Bluefin.Compound+--   deriving (Handle) via OneWayCoercibleHandle ExAndPrim+--   deriving stock (Generic)+--+-- instance (e \<: es) => OneWayCoercible (ExAndPrim e) (ExAndPrim es) where+--   oneWayCoercibleImpl = gOneWayCoercible+--+-- -- Define a monad M containing the Prim capability+-- newtype M e es a = MkM (ReaderT (ExAndPrim e) (Eff es) a)+--   deriving newtype (Functor, Applicative, Monad)+--+-- -- Define a way of running M+-- runM ::+--   (e1 \<: es, e2 \<: es) =>+--   Exception String e1 ->+--   P.Prim e2 ->+--   M es es r ->+--   Eff es r+-- runM ex prim (MkM m) =+--   runReaderT m (MkExAndPrim (mapHandle ex) (mapHandle prim))+--+-- -- Give M a PrimMonad instance+-- instance (e \<: es) => PrimMonad (M e es) where+--   type PrimState (M e es) = P.PrimStateEff e+--   primitive f =+--     MkM (ReaderT (\\(MkExAndPrim _ prim) -> P.'primitive' prim f))+--+-- -- ghci> example+-- -- Right [\"Hello\",\"World\"]+-- example :: Either String [String]+-- example = runPureEff $ try $ \\ex -> P.'runPrim' $ \\prim -> do+--   runM ex prim $ do+--     arr <- A.newArray 2 \"Hello\"+--     A.writeArray arr 1 \"World\"+--     for [0, 1] (A.readArray arr)+-- @+module Bluefin.Prim (Prim, runPrim, PrimStateEff, primitive) where++import Bluefin.Internal.Prim
src/Bluefin/Reader.hs view
@@ -1,6 +1,12 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.Ask" instead. module Bluefin.Reader   ( -- | 'Reader' is Bluefin's version of the-    -- "Control.Monad.Trans.Reader" monad.+    -- "Control.Monad.Trans.Reader" monad.  'local' allows you to+    -- locally override the value in the @Reader@ capability in a+    -- well-scoped way.  The original value will be restored when you+    -- exit the @local@ block regardless of whether the exit was+    -- normal or via an exception .      -- * Handle     Reader,
src/Bluefin/State.hs view
@@ -1,10 +1,15 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.Modify"+-- instead. module Bluefin.State   ( -- * Handle     State,+     -- * Handlers     evalState,     runState,     withState,+     -- * Effectful operations     get,     put,
src/Bluefin/StateSource.hs view
@@ -1,6 +1,6 @@ module Bluefin.StateSource   ( -- | A 'StateSource' allows you to allocate new-    -- 'Bluefin.State.State' handles, much like 'Control.Monad.ST'+    -- t'Bluefin.State.State' handles, much like t'Control.Monad.ST'     -- allows you to allocate new 'Data.STRef.STRef's.  This can be     -- useful when you want to avoid nested 'Bluefin.State.runState'     -- (or `Bluefin.State.evalState') blocks, or you need a number
src/Bluefin/Stream.hs view
@@ -1,13 +1,20 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.Yield"+-- instead. module Bluefin.Stream   ( -- | 'Stream' allows you to yield values during the execution of a     -- Bluefin operation.  It provides similar functionality to     -- Python's @yield@.  The handler of the 'Stream' will either     -- handle each element as soon as it is yielded (for example-    -- 'forEach') or gather all yielded elements int o a list (for+    -- 'forEach') or gather all yielded elements into a list (for     -- example 'yieldToList').+    --+    -- For information about prompt finalization/resource safety when+    -- using Bluefin @Stream@s, see "Bluefin.Coroutine".      -- * Handle     Stream,+     -- * Handlers     forEach,     yieldToList,@@ -20,6 +27,7 @@     catMaybes,     consumeStream,     streamConsume,+     -- * Effectful operations     yield,     inFoldable,
src/Bluefin/System/IO.hs view
@@ -1,5 +1,4 @@ -- | A safer interface to @System.IO.'System.IO.Handle'@- module Bluefin.System.IO   ( -- * Handle     Handle,@@ -16,7 +15,6 @@     hFlush,      -- * Unsafe-     unsafeWithHandle,   ) where
src/Bluefin/Writer.hs view
@@ -1,3 +1,6 @@+-- | This is an old interface and will be deprecated in the+-- future. You are encouraged to use "Bluefin.Capability.Writer"+-- instead. module Bluefin.Writer   ( -- | In most cases you'll probably prefer t'Bluefin.Stream.Stream'     -- to @Writer@, but @Writer@ can still be useful in some cases,@@ -6,9 +9,11 @@      -- * Handle     Writer,+     -- * Handlers     runWriter,     execWriter,+     -- * Effectful operations     tell,   )