bluefin-internal 0.0.8.0 → 0.0.9.0
raw patch · 5 files changed
+98/−16 lines, 5 filesdep ~asyncPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: async
API changes (from Hackage documentation)
+ Bluefin.Internal: instance Bluefin.Internal.Handle Bluefin.Internal.IOE
+ Bluefin.Internal: rethrowIO :: forall ex es e1 e2 r. (e1 :> es, e2 :> es, Exception ex) => IOE e1 -> Exception ex e2 -> Eff es r -> Eff es r
+ Bluefin.Internal.Examples: doubleNestedForEach :: (forall e. Stream () e -> Eff (e :& es) ()) -> Eff es ()
+ Bluefin.Internal.Examples: rethrowIOExample :: IO ()
Files
- CHANGELOG.md +6/−0
- bluefin-internal.cabal +2/−2
- src/Bluefin/Internal.hs +49/−1
- src/Bluefin/Internal/Examples.hs +21/−0
- test/Main.hs +20/−13
CHANGELOG.md view
@@ -1,3 +1,9 @@+## 0.0.9.0++* Add `instance Handle IOE`++* Add `rethrowIO`+ ## 0.0.8.0 Add `Consume`, `await`, `consumeStream`, `zipCoroutines`,
bluefin-internal.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: bluefin-internal-version: 0.0.8.0+version: 0.0.9.0 license: MIT license-file: LICENSE author: Tom Ellis@@ -77,7 +77,7 @@ default-language: Haskell2010 hs-source-dirs: src build-depends:- async,+ async >= 2.2 && < 2.3, base >= 4.12 && < 4.21, unliftio-core < 0.3, transformers < 0.7,
src/Bluefin/Internal.hs view
@@ -243,7 +243,7 @@ insertFirst = weakenEff (drop (eq (# #))) insertSecond :: Eff (c1 :& b) r -> Eff (c1 :& (c2 :& b)) r-insertSecond = weakenEff (b (drop (eq (# #))))+insertSecond = insertManySecond insertManySecond :: (b :> c) => Eff (c1 :& b) r -> Eff (c1 :& c) r insertManySecond = weakenEff (bimap has has)@@ -355,6 +355,9 @@ instance Handle (Writer w) where mapHandle (Writer wr) = Writer (mapHandle wr) +instance Handle IOE where+ mapHandle MkIOE = MkIOE+ newtype In (a :: Effects) (b :: Effects) = In# (# #) merge :: (# #) -> (a :& a) `In` a@@ -489,6 +492,51 @@ (exn -> Eff es a) -> Eff es a catch f h = handle h f++-- We really do need to have an IOE argument here because, it is not+-- determined which of Ex1 or Ex2 is produced in the following code,+-- due to pure exceptions being imprecise.+--+-- f :: IO (Either Ex1 (Either Ex2 a))+-- f = runEff $ \io -> do+-- try $ \e1 -> do+-- try $ \e2 -> do+-- rethrowIO io e1 $ do+-- rethrowIO io e2 $ doa+-- Control.Exception.throw Ex1) (Control.Exception.throw E2)++-- | Rethrow an exception raised by an 'IO' action as a Bluefin+-- exception.+--+-- @+-- 'runEff' $ \\io -> do+-- r \<- 'try' $ \\ex -> do+-- rethrowIO @'Control.Exception.IOException' io ex $ do+-- effIO io ('Prelude.readFile' "\/tmp\/doesnt-exist")+--+-- 'effIO' io $ putStrLn $ case r of+-- Left e -> "Caught IOException:\\n" ++ show e+-- Right contents -> contents+-- @+--+-- @+-- Caught ErrorCall:+-- \/tmp\/doesnt-exist: openFile: does not exist (No such file or directory)+-- @+rethrowIO ::+ forall ex es e1 e2 r.+ (e1 :> es, e2 :> es, Control.Exception.Exception ex) =>+ IOE e1 ->+ Exception ex e2 ->+ Eff es r ->+ -- | ͘+ Eff es r+rethrowIO MkIOE ex body =+ UnsafeMkEff+ ( Control.Exception.catch+ (unsafeUnEff body)+ (\e -> unsafeUnEff (throw @_ @es ex e))+ ) -- | @bracket acquire release body@: @acquire@ a resource, perform the -- @body@ with it, and @release@ the resource even if @body@ threw an
src/Bluefin/Internal/Examples.hs view
@@ -77,6 +77,17 @@ yield y 100 pure length +-- This shows we can use forEach at any level of nesting with+-- insertManySecond+doubleNestedForEach ::+ (forall e. Stream () e -> Eff (e :& es) ()) ->+ Eff es ()+doubleNestedForEach f =+ withState () $ \_ -> do+ withState () $ \_ -> do+ forEach (insertManySecond . f) (\_ -> pure ())+ pure (\_ _ -> ())+ forEachExample :: ([Int], ()) forEachExample = runPureEff $ yieldToList $ \y -> do forEach (inFoldable [0 .. 4]) $ \i -> do@@ -877,3 +888,13 @@ (\_ -> for_ [1 :: Int ..] $ \i -> yield y i) ) effIO io (putStrLn "Finishing")++rethrowIOExample :: IO ()+rethrowIOExample = runEff $ \io -> do+ r <- try $ \ex -> do+ rethrowIO @Control.Exception.IOException io ex $ do+ effIO io (Prelude.readFile "/tmp/doesnt-exist")++ effIO io $ putStrLn $ case r of+ Left e -> "Caught IOException:\n" ++ show e+ Right contents -> contents
test/Main.hs view
@@ -11,8 +11,8 @@ import Prelude hiding (break, read) main :: IO ()-main = do- runSpecH $ \y -> do+main = runEff $ \io -> do+ runSpecH io $ \y -> do let assertEqual' = assertEqual y assertEqual' "oddsUntilFirstGreaterThan5" oddsUntilFirstGreaterThan5 [1, 3, 5, 7]@@ -53,26 +53,31 @@ yield y2 ("But got: " ++ show c2) ) -type SpecInfo = Forall (Nest (Stream String) Eff)+type SpecInfo r = Forall (Stream String :~> WrapEff r) withSpecInfo :: (forall e es. (e :> es) => Stream String e -> Eff es r) -> SpecInfo r-withSpecInfo x = Forall (Nest x)+withSpecInfo x = Forall (Nest (\s -> MkWrapEff (x s))) -newtype Nest h t es r = Nest {unNest :: forall e. (e :> es) => h e -> t es r}+newtype (h :~> t) es = Nest {unNest :: forall e. h e -> t (e :& es)} -newtype Forall t r = Forall {unForall :: forall es. t es r}+newtype Forall t = Forall {unForall :: forall es. t es} +newtype WrapEff r es = MkWrapEff {unWrapEff :: Eff es r}++instance Handle (WrapEff r) where+ mapHandle (MkWrapEff e) = MkWrapEff (useImpl e)+ runTests :: forall es e3. (e3 :> es) =>- (forall e1 e2. SpecH e1 -> Eff (e1 :& e2 :& es) ()) ->+ (forall e1. SpecH e1 -> Eff (e1 :& es) ()) -> Stream String e3 -> Eff es Bool runTests f y = do ((), All passedAll) <- runWriter $ \passedAllSoFar -> do- forEach f $ \(name, mFailure) -> do+ forEach (useImplWithin f) $ \(name, mFailure) -> do let passed = case mFailure of Just _ -> False Nothing -> True@@ -87,17 +92,19 @@ Nothing -> pure () Just n -> do yield y "" :: Eff (e2 :& es) ()- _ <- forEach (unNest (unForall n)) $ \entry -> do+ _ <- forEach (unWrapEff . unNest (unForall n)) $ \entry -> do yield y (" " ++ entry) yield y "" pure passedAll runSpecH ::- (forall e1 es. SpecH e1 -> Eff (e1 :& es) ()) ->- IO ()-runSpecH f = runEff $ \ioe -> do- passed <- forEach (runTests f) $ \text ->+ (e :> es) =>+ IOE e ->+ (forall e1. SpecH e1 -> Eff (e1 :& es) ()) ->+ Eff es ()+runSpecH ioe f = do+ passed <- forEach (runTests (useImplWithin f)) $ \text -> effIO ioe (putStrLn text) effIO ioe $ case passed of