bluefin 0.0.11.0 → 0.0.12.0
raw patch · 4 files changed
+69/−16 lines, 4 filesdep ~bluefin-internalPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: bluefin-internal
API changes (from Hackage documentation)
+ Bluefin.Reader: asks :: forall (e :: Effects) (es :: Effects) r a. e :> es => Reader r e -> (r -> a) -> Eff es a
+ Bluefin.Reader: local :: forall (e1 :: Effects) (es :: Effects) r a. e1 :> es => Reader r e1 -> (r -> r) -> Eff es a -> Eff es a
Files
- CHANGELOG.md +4/−0
- bluefin.cabal +2/−2
- src/Bluefin/Compound.hs +60/−10
- src/Bluefin/Reader.hs +3/−4
CHANGELOG.md view
@@ -1,3 +1,7 @@+## 0.0.12.0++* Add `asks` and `local` to `Bluefin.Reader`+ ## 0.0.11.0 * Add `withEffToIO_`, `useImplUnder`, `makeOp`
bluefin.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: bluefin-version: 0.0.11.0+version: 0.0.12.0 license: MIT license-file: LICENSE author: Tom Ellis@@ -38,6 +38,6 @@ Bluefin.System.IO, Bluefin.Writer, build-depends:- bluefin-internal >= 0.0.11.0 && < 0.1+ bluefin-internal >= 0.0.12.0 && < 0.1 hs-source-dirs: src default-language: Haskell2010
src/Bluefin/Compound.hs view
@@ -134,13 +134,56 @@ -- 10 -- @ - -- ** Wrap multiple effects, don't handle them all+ -- ** Wrap a single effect, don't handle it -- | So far our handlers have handled all the effects that are -- found within our compound effect. We don't have to do that- -- though: we can leave some of the effects unhandled to be- -- handled by a different handler at a higher level. Let's extend- -- our example with a @Stream@ effect. Whenever we ask to+ -- 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.IO.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 (IOE e)+ --+ -- incCounter3B :: (e :> es) => Counter3B e -> Eff es ()+ -- incCounter3B (MkCounter3B io) =+ -- effIO io (putStrLn "You tried to increment the counter")+ --+ -- runCounter3B ::+ -- (e1 :> es) =>+ -- IOE e1 ->+ -- (forall e. Counter3B e -> Eff (e :& es) r) ->+ -- Eff es r+ -- runCounter3B io k = useImplIn k (MkCounter3B (mapHandle io))+ -- @+ --+ -- @+ -- exampleCounter3B :: IO ()+ -- exampleCounter3B = runEff $ \\io -> runCounter3B io $ \\c -> do+ -- incCounter3B c+ -- incCounter3B c+ -- incCounter3B c+ -- @+ --+ -- This isn't a terribly useful counter! It doesn't actually+ -- increment anything, it just prints a message when we try, but+ -- the example does demonstrate how to wrap @IOE@.+ --+ -- @+ -- -- ghci> exampleCounter3B+ -- -- You tried to increment the counter+ -- -- You tried to increment the counter+ -- -- You tried to increment the counter+ -- @++ -- ** Wrap multiple effects, don't handle them all++ -- | We can wrap multiple effects, handle some of them and leave+ -- the others to be handled later. Let's extend @Counter3@ with a+ -- @Stream@ effect. Whenever we ask to -- increment the counter, and it is currently an even number, then -- we yield a message about that. Additionally, there's a new -- operation @getCounter4@ which allows us to yield a message@@ -208,7 +251,7 @@ -- @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 @useImpl@.+ -- from the record fields by applying @makeOp@. -- -- @ -- data Counter5 e = MkCounter5@@ -428,7 +471,7 @@ -- @ -- -- ... unless we run @incCounter@ too many times, in which case it- -- throws can exception.+ -- throws an exception. -- -- @ -- exampleCounter7B :: ([String], Int)@@ -451,15 +494,22 @@ -- -- @ -- data FileSystem es = MkFileSystem- -- { readFileImpl :: FilePath -> Eff es String,- -- writeFileImpl :: FilePath -> String -> Eff es ()+ -- { readFileImpl :: forall e. FilePath -> Eff (e :& es) String,+ -- writeFileImpl :: forall e. FilePath -> String -> Eff (e :& es) () -- } --+ -- instance Handle FileSystem where+ -- mapHandle fs = MkFileSystem {+ -- readFileImpl = \\fp -> useImplUnder (readFileImpl fs fp),+ -- writeFileImpl = \\fp s -> useImplUnder (writeFileImpl fs fp s)+ -- }+ -- -- readFile :: (e :> es) => FileSystem e -> FilePath -> Eff es String- -- readFile fs filepath = useImpl (readFileImpl fs filepath)+ -- readFile fs filepath = makeOp (readFileImpl (mapHandle fs) filepath) -- -- writeFile :: (e :> es) => FileSystem e -> FilePath -> String -> Eff es ()- -- writeFile fs filepath contents = useImpl (writeFileImpl fs filepath contents)+ -- writeFile fs filepath contents =+ -- makeOp (writeFileImpl (mapHandle fs) filepath contents) -- @ -- -- We can make a pure handler that simulates reading and writing
src/Bluefin/Reader.hs view
@@ -1,9 +1,6 @@ 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.+ -- "Control.Monad.Trans.Reader" monad. -- * Handle Reader,@@ -13,6 +10,8 @@ -- * Effectful operations ask,+ asks,+ local, ) where