bluefin 0.0.2.0 → 0.0.3.0
raw patch · 6 files changed
+128/−7 lines, 6 filesdep ~bluefin-internalPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: bluefin-internal
API changes (from Hackage documentation)
+ Bluefin.Reader: ask :: forall (e :: Effects) (es :: Effects) r. e :> es => Reader r e -> Eff es r
+ Bluefin.Reader: data () => Reader r (e :: Effects)
+ Bluefin.Reader: runReader :: forall r (es :: Effects) a. r -> (forall (e :: Effects). () => Reader r e -> Eff (e :& es) a) -> Eff es a
Files
- bluefin.cabal +4/−3
- src/Bluefin.hs +94/−0
- src/Bluefin/Jump.hs +1/−1
- src/Bluefin/Reader.hs +19/−0
- src/Bluefin/StateSource.hs +2/−2
- src/Bluefin/Stream.hs +8/−1
bluefin.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: bluefin-version: 0.0.2.0+version: 0.0.3.0 license: MIT license-file: LICENSE author: Tom Ellis@@ -26,13 +26,14 @@ Bluefin.EarlyReturn, Bluefin.Eff, Bluefin.Exception,- Bluefin.Jump, Bluefin.IO,+ Bluefin.Jump,+ Bluefin.Reader, Bluefin.State, Bluefin.StateSource, Bluefin.Stream, Bluefin.Writer, build-depends:- bluefin-internal >= 0.0.1 && < 0.1+ bluefin-internal >= 0.0.3 && < 0.1 hs-source-dirs: src default-language: Haskell2010
src/Bluefin.hs view
@@ -93,6 +93,97 @@ -- finished running there is no way you can use the handle -- anymore. + -- ** Type signatures++ -- | Bluefin type signatures follow a common pattern which looks+ -- like+ --+ -- @+ -- (e1 :> es, ...) -> \<Handle\> e1 -> ... -> Eff es r+ -- @+ --+ --+ -- Consider the example below, @incrementReadLine@, which reads+ -- integers from standard input and 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,+ -- 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+ -- polymorphic.+ --+ -- Secondly, let's look at the return value, @Eff es ()@. This+ -- means the computation is performed in the t'Bluefin.Eff.Eff'+ -- monad and the resulting value produced is of type @()@. @Eff@+ -- is tagged with the effect type @es@, which is also always kept+ -- polymorphic.+ --+ -- 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+ -- 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+ -- actually used anywhere in the computation.+ --+ -- GHC and editor tools like HLS do a good job of inferring these+ -- type signatures.+ --+ -- @+ -- incrementReadLine ::+ -- (e1 :> es, e2 :> es, e3 :> es) =>+ -- State Int e1 ->+ -- Exception String e2 ->+ -- IOE e3 ->+ -- Eff es ()+ -- incrementReadLine state exception io = do+ -- 'Bluefin.Jump.withJump' $ \\break -> 'Control.Monad.forever' $ do+ -- line <- 'Bluefin.IO.effIO' io getLine+ -- i <- case 'Text.Maybe.readMaybe' line of+ -- Nothing ->+ -- 'Bluefin.Exception.throw' exception ("Couldn't read: " ++ line)+ -- Just i ->+ -- pure i+ --+ -- when (i == 0) $+ -- 'Bluefin.Jump.jumpTo' break+ --+ -- 'Bluefin.State.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.+ --+ -- @+ -- runIncrementReadLine :: IO (Either String Int)+ -- runIncrementReadLine = 'Bluefin.Eff.runEff' $ \\io -> do+ -- 'Bluefin.Exception.try' $ \\exception -> do+ -- ((), r) \<- 'Bluefin.State.runState' 0 $ \\state -> do+ -- incrementReadLine state exception io+ -- pure r+ --+ -- >>> runIncrementReadLine+ -- 1+ -- 2+ -- 3+ -- 0+ -- Right 6+ -- >>>> runIncrementReadLine+ -- 1+ -- 2+ -- 3+ -- Hello+ -- Left "Couldn't read: Hello"+ -- @+ -- * Comparison to other effect systems -- ** Everything except effectful@@ -153,6 +244,9 @@ -- there are no unhandled effects it is safe to run the underlying -- @IO@ action using 'System.IO.Unsafe.unsafePerformIO', which is -- the approach taken to implement 'Bluefin.Eff.runPureEff'.+ -- Consequently, it is impossible for a pure value retured from+ -- `runPureEff` to access any Bluefin internal state or throw a+ -- Bluefin internal exception. -- * Tips
src/Bluefin/Jump.hs view
@@ -1,5 +1,5 @@ module Bluefin.Jump- ( -- | Jump allows you to jump back to a previously-set location.+ ( -- | 'Jump' allows you to jump back to a previously-set location. -- It is not documented yet. -- * Handle
+ src/Bluefin/Reader.hs view
@@ -0,0 +1,19 @@+module Bluefin.Reader+ ( -- | 'Reader' is Bluefin's version of the+ -- "Control.Monad.Trans.Reader" monad. Passing around a @Reader r+ -- e@ is equivalent to just passing around an @r@, and as such it+ -- is essentially redundant and we don't know of any reasons to+ -- use it in practice. It is included for completeness, however.++ -- * Handle+ Reader,++ -- * Handlers+ runReader,++ -- * Effectful operations+ ask,+ )+where++import Bluefin.Internal
src/Bluefin/StateSource.hs view
@@ -3,8 +3,8 @@ -- 'Bluefin.State.State' handles, much like '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 an only- -- dynamically known number of mutable states.+ -- (or `Bluefin.State.evalState') blocks, or you need a number+ -- of mutable states that is only dynamically known. -- * Handle StateSource,
src/Bluefin/Stream.hs view
@@ -1,5 +1,12 @@ module Bluefin.Stream- ( -- * Handle+ ( -- | '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+ -- example 'yieldToList').++ -- * Handle Stream, -- * Handlers forEach,