packages feed

bluefin-internal 0.10.1.0 → 0.11.0.0

raw patch · 10 files changed

+199/−71 lines, 10 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Bluefin.Internal: withScopedException_ :: ((forall a. () => e -> IO a) -> IO r) -> IO (Either e r)
- Bluefin.Internal.DslBuilderEffects: MkDslBuilderEffects :: (forall (e :: Effects). () => h e -> Eff (e :& es) r) -> DslBuilderEffects (h :: Effects -> Type) (es :: Effects) r
- Bluefin.Internal.DslBuilderEffects: [unMkDslBuilderEffects] :: DslBuilderEffects (h :: Effects -> Type) (es :: Effects) r -> forall (e :: Effects). () => h e -> Eff (e :& es) r
- Bluefin.Internal.DslBuilderEffects: dslBuilderEffects :: forall h (es :: Effects) r. (forall (e :: Effects). () => h e -> Eff (e :& es) r) -> DslBuilderEffects h es r
- Bluefin.Internal.DslBuilderEffects: instance (e Bluefin.Internal.<: es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.DslBuilderEffects.DslBuilderEffects h e r) (Bluefin.Internal.DslBuilderEffects.DslBuilderEffects h es r)
- Bluefin.Internal.DslBuilderEffects: instance Bluefin.Internal.Handle h => GHC.Base.Applicative (Bluefin.Internal.DslBuilderEffects.DslBuilderEffects h es)
- Bluefin.Internal.DslBuilderEffects: instance Bluefin.Internal.Handle h => GHC.Base.Functor (Bluefin.Internal.DslBuilderEffects.DslBuilderEffects h es)
- Bluefin.Internal.DslBuilderEffects: instance Bluefin.Internal.Handle h => GHC.Base.Monad (Bluefin.Internal.DslBuilderEffects.DslBuilderEffects h es)
- Bluefin.Internal.DslBuilderEffects: newtype DslBuilderEffects (h :: Effects -> Type) (es :: Effects) r
- Bluefin.Internal.DslBuilderEffects: runDslBuilderEffects :: forall h (es :: Effects) r. h es -> DslBuilderEffects h es r -> Eff es r
- Bluefin.Internal.DslBuilderEffects: useImplDslBuilderEffects :: forall (e :: Effects) (es :: Effects) (h :: Effects -> Type) r. e <: es => DslBuilderEffects h e r -> DslBuilderEffects h es r
+ Bluefin.Internal: MkThrowCatch :: Exception ex -> ThrowCatch ex (e :: Effects)
+ Bluefin.Internal: instance (e Bluefin.Internal.<: es) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.ThrowCatch ex e) (Bluefin.Internal.ThrowCatch ex es)
+ Bluefin.Internal: instance Bluefin.Internal.Handle (Bluefin.Internal.ThrowCatch ex)
+ Bluefin.Internal: newtype ThrowCatch ex (e :: Effects)
+ Bluefin.Internal: throwCatchThrow :: forall (e :: Effects) (es :: Effects) ex a. e <: es => ThrowCatch ex e -> ex -> Eff es a
+ Bluefin.Internal: throwCatchTry :: forall ex (es :: Effects) a. (forall (e :: Effects). () => ThrowCatch ex e -> Eff (e :& es) a) -> Eff es (Either ex a)
+ Bluefin.Internal.Capability.ThrowCatch: catch :: forall ex (es :: Effects) a. (forall (e :: Effects). () => ThrowCatch ex e -> Eff (e :& es) a) -> (ex -> Eff es a) -> Eff es a
+ Bluefin.Internal.Capability.ThrowCatch: data ThrowCatch ex (e :: Effects)
+ Bluefin.Internal.Capability.ThrowCatch: handle :: forall ex (es :: Effects) a. (ex -> Eff es a) -> (forall (e :: Effects). () => ThrowCatch ex e -> Eff (e :& es) a) -> Eff es a
+ Bluefin.Internal.Capability.ThrowCatch: localCatch :: forall (e :: Effects) (es :: Effects) ex a. e <: es => ThrowCatch ex e -> Eff es a -> (ex -> Eff es a) -> Eff es a
+ Bluefin.Internal.Capability.ThrowCatch: localHandle :: forall (e :: Effects) (es :: Effects) ex a. e <: es => ThrowCatch ex e -> (ex -> Eff es a) -> Eff es a -> Eff es a
+ Bluefin.Internal.Capability.ThrowCatch: localTry :: forall (e :: Effects) (es :: Effects) ex a. e <: es => ThrowCatch ex e -> Eff es a -> Eff es (Either ex a)
+ Bluefin.Internal.Capability.ThrowCatch: throw :: forall (e :: Effects) (es :: Effects) ex a. e <: es => ThrowCatch ex e -> ex -> Eff es a
+ Bluefin.Internal.Capability.ThrowCatch: try :: forall ex (es :: Effects) a. (forall (e :: Effects). () => ThrowCatch ex e -> Eff (e :& es) a) -> Eff es (Either ex a)
+ Bluefin.Internal.DslBuilderEff: runDslBuilderEffMappedArgs :: forall (e1 :: Effects) (e2 :: Effects) (es :: Effects) h r. (Handle h, e1 <: es, e2 <: es) => h e1 -> DslBuilderEff h e2 r -> Eff es r
+ Bluefin.Internal.Exception.Scoped: localTry :: Exception e -> IO a -> IO (Either e a)
- Bluefin.Internal.DslBuilder: MkDslBuilder :: Forall (DslBuilderEffects h) r -> DslBuilder (h :: Effects -> Type) r
+ Bluefin.Internal.DslBuilder: MkDslBuilder :: Forall (DslBuilderEff h) r -> DslBuilder (h :: Effects -> Type) r
- Bluefin.Internal.DslBuilder: [unMkDslBuilder] :: DslBuilder (h :: Effects -> Type) r -> Forall (DslBuilderEffects h) r
+ Bluefin.Internal.DslBuilder: [unMkDslBuilder] :: DslBuilder (h :: Effects -> Type) r -> Forall (DslBuilderEff h) r

Files

CHANGELOG.md view
@@ -1,3 +1,21 @@+# 0.11.0.0++* Add `Bluefin.Internal.Capability.ThrowCatch`++* Add `ThrowCatch`, `throwCatchThrow`, `throwCatchTry`++* Remove `withScopedException_`++* Add `Bluefin.Internal.DslBuilderEff.runDslBuilderEffMappedArgs`++* Remove `Bluefin.Internal.DslBuilderEffects`++# 0.10.1.0++* Add `runPureEffAsyncSafe` and `runPureEffAsyncSafeRestarting`++* Use `INLINE [0]` on `runDslBuilderEff` for improved performance+ # 0.10.0.0  * Make `Ask`, `AskCapability`, `Await`, `JumpTo`, `Modify`, `Request`,
bluefin-internal.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               bluefin-internal-version:            0.10.1.0+version:            0.11.0.0 license:            MIT license-file:       LICENSE author:             Tom Ellis@@ -89,9 +89,9 @@       Bluefin.Internal.CloneableHandle,       Bluefin.Internal.DslBuilder,       Bluefin.Internal.DslBuilderEff,-      Bluefin.Internal.DslBuilderEffects,       Bluefin.Internal.Examples,       Bluefin.Internal.Exception,+      Bluefin.Internal.Capability.ThrowCatch,       Bluefin.Internal.Exception.Scoped,       Bluefin.Internal.GadtEffect,       Bluefin.Internal.Key,@@ -108,7 +108,8 @@     main-is:          Main.hs     other-modules:    Test.GeneralBracket,                       Test.RunPureEff,-                      Test.SpecH+                      Test.SpecH,+                      Test.ThrowCatch     build-depends:         base,         async,
src/Bluefin/Internal.hs view
@@ -441,6 +441,20 @@ instance (e <: es) => OneWayCoercible (Throw ex e) (Throw ex es) where   oneWayCoercibleImpl = oneWayCoercible +-- | A scoped exception capability that can catch within its own scope.+type ThrowCatch :: Type -> Effects -> Type+newtype ThrowCatch ex e+  = MkThrowCatch (ScopedException.Exception ex)+  deriving (Handle) via OneWayCoercibleHandle (ThrowCatch ex)++type role ThrowCatch nominal nominal++instance+  (e <: es) =>+  OneWayCoercible (ThrowCatch ex e) (ThrowCatch ex es)+  where+  oneWayCoercibleImpl = unsafeOneWayCoercible+ -- | Capability to modify a reference to an @s@ newtype Modify s (e :: Effects) = UnsafeMkState (IORef s)   deriving (Handle) via OneWayCoercibleHandle (Modify s)@@ -847,6 +861,14 @@   Eff es a throw h = case mapHandle h of MkException throw_ -> throw_ +throwCatchThrow ::+  (e <: es) =>+  ThrowCatch ex e ->+  ex ->+  Eff es a+throwCatchThrow (MkThrowCatch ex) exn =+  unsafeProvideIO $ \io -> effIO io (ScopedException.throw ex exn)+ has :: forall a b. (a <: b) => a `In` b -- This is safe because, as shown by instanceProof1/2/3, the only way -- to construct `a <: b` is if `a `In` b`.@@ -875,10 +897,17 @@   -- | @Left@ if the exception was thrown, @Right@ otherwise   Eff es (Either exn a) try f =+  throwCatchTry $ \ex ->+    f (MkException (throwCatchThrow ex))++throwCatchTry ::+  (forall e. ThrowCatch ex e -> Eff (e :& es) a) ->+  Eff es (Either ex a)+throwCatchTry f =   unsafeProvideIO $ \io -> do     withEffToIO_ io $ \effToIO -> do-      withScopedException_ $ \throw_ -> do-        effToIO (f (MkException (effIO io . throw_)))+      ScopedException.try $ \ex -> do+        effToIO (f (MkThrowCatch ex))  -- | -- @@@ -1059,10 +1088,6 @@ modify state f = do   s <- get state   put state (f s)--withScopedException_ :: ((forall a. e -> IO a) -> IO r) -> IO (Either e r)-withScopedException_ f =-  ScopedException.try (\ex -> f (ScopedException.throw ex))  -- | -- @
+ src/Bluefin/Internal/Capability/ThrowCatch.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE ExplicitNamespaces #-}+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}++module Bluefin.Internal.Capability.ThrowCatch+  ( ThrowCatch,+    module Bluefin.Internal.Capability.ThrowCatch,+  )+where++import Bluefin.Internal+  ( ThrowCatch (MkThrowCatch),+    Eff,+    throwCatchTry,+    throwCatchThrow,+    unsafeProvideIO,+    useImpl,+    withEffToIO_,+    (:&),+    type (<:),+  )+import Bluefin.Internal.Exception.Scoped qualified as Scoped++try ::+  (forall e. ThrowCatch ex e -> Eff (e :& es) a) ->+  -- | ͘+  Eff es (Either ex a)+try = throwCatchTry++handle ::+  (ex -> Eff es a) ->+  (forall e. ThrowCatch ex e -> Eff (e :& es) a) ->+  -- | ͘+  Eff es a+handle h f =+  try f >>= \case+    Left ex -> h ex+    Right a -> pure a++catch ::+  (forall e. ThrowCatch ex e -> Eff (e :& es) a) ->+  (ex -> Eff es a) ->+  -- | ͘+  Eff es a+catch f h = handle h f++localCatch ::+  (e <: es) =>+  ThrowCatch ex e ->+  Eff es a ->+  (ex -> Eff es a) ->+  -- | ͘+  Eff es a+localCatch h action handler =+  localTry h action >>= \case+    Left ex -> handler ex+    Right a -> pure a++localHandle ::+  (e <: es) =>+  ThrowCatch ex e ->+  (ex -> Eff es a) ->+  Eff es a ->+  -- | ͘+  Eff es a+localHandle h handler action = localCatch h action handler++throw ::+  (e <: es) =>+  ThrowCatch ex e ->+  ex ->+  -- | ͘+  Eff es a+throw = throwCatchThrow++localTry ::+  (e <: es) =>+  ThrowCatch ex e ->+  Eff es a ->+  -- | ͘+  Eff es (Either ex a)+localTry h action = case h of+  MkThrowCatch ex ->+    unsafeProvideIO $ \io ->+      withEffToIO_ io $ \runInIO ->+        Scoped.localTry ex (runInIO (useImpl action))
src/Bluefin/Internal/DslBuilder.hs view
@@ -3,11 +3,7 @@ module Bluefin.Internal.DslBuilder where  import Bluefin.Internal-import Bluefin.Internal.DslBuilderEffects-  ( DslBuilderEffects,-    dslBuilderEffects,-    runDslBuilderEffects,-  )+import Bluefin.Internal.DslBuilderEff  newtype Forall f r = MkForall {unForall :: forall es. f es r} @@ -27,13 +23,13 @@     unForall (f r)  newtype DslBuilder h r-  = MkDslBuilder {unMkDslBuilder :: Forall (DslBuilderEffects h) r}+  = MkDslBuilder {unMkDslBuilder :: Forall (DslBuilderEff h) r}  runDslBuilder :: (Handle h) => h es -> DslBuilder h r -> Eff es r-runDslBuilder h f = runDslBuilderEffects h (unForall (unMkDslBuilder f))+runDslBuilder h f = runDslBuilderEff h (unForall (unMkDslBuilder f))  dslBuilder :: (forall e. h e -> Eff e r) -> DslBuilder h r-dslBuilder k = MkDslBuilder (mkForall (dslBuilderEffects (useImpl . k)))+dslBuilder k = MkDslBuilder (mkForall (dslBuilderEff (useImpl . k)))  instance (Handle h) => Functor (DslBuilder h) where   fmap f g = dslBuilder (\h -> fmap f (runDslBuilder h g))
src/Bluefin/Internal/DslBuilderEff.hs view
@@ -38,6 +38,18 @@  -- oneShot is essential for good performance. I don't fully understand -- why.++runDslBuilderEffMappedArgs ::+  forall e1 e2 es h r.+  (Handle h, e1 <: es, e2 <: es) =>+  h e1 ->+  DslBuilderEff h e2 r ->+  -- | ͘+  Eff es r+runDslBuilderEffMappedArgs h f =+  runDslBuilderEff (mapHandle h) (useImplDslBuilderEff f)+{-# INLINE runDslBuilderEffMappedArgs #-}+ dslBuilderEff ::   (forall e. h e -> Eff (e :& es) r) ->   -- | ͘@@ -56,15 +68,15 @@ instance (Handle h) => Functor (DslBuilderEff h es) where   fmap f g =     dslBuilderEff $ \h ->-      fmap f (runDslBuilderEff (mapHandle h) (useImplDslBuilderEff g))+      fmap f (runDslBuilderEffMappedArgs h g)  instance (Handle h) => Applicative (DslBuilderEff h es) where   pure x = dslBuilderEff (pure (pure x))   f <*> x = dslBuilderEff $ \h ->-    runDslBuilderEff (mapHandle h) (useImplDslBuilderEff f)-      <*> runDslBuilderEff (mapHandle h) (useImplDslBuilderEff x)+    runDslBuilderEffMappedArgs h f+      <*> runDslBuilderEffMappedArgs h x  instance (Handle h) => Monad (DslBuilderEff h es) where   m >>= f = dslBuilderEff $ \h -> do-    r <- runDslBuilderEff (mapHandle h) (useImplDslBuilderEff m)-    runDslBuilderEff (mapHandle h) (useImplDslBuilderEff (f r))+    r <- runDslBuilderEffMappedArgs h m+    runDslBuilderEffMappedArgs h (f r)
− src/Bluefin/Internal/DslBuilderEffects.hs
@@ -1,48 +0,0 @@--- This will probably be superseded by DslBuilderEff because the--- latter has a better name-{-# LANGUAGE DerivingVia #-}-{-# LANGUAGE QuantifiedConstraints #-}--module Bluefin.Internal.DslBuilderEffects where--import Bluefin.Internal-import Bluefin.Internal.OneWayCoercible-  ( OneWayCoercible,-    oneWayCoerce,-    oneWayCoercible,-    oneWayCoercibleImpl,-  )--newtype DslBuilderEffects h es r-  = MkDslBuilderEffects {unMkDslBuilderEffects :: forall e. h e -> Eff (e :& es) r}--useImplDslBuilderEffects :: (e <: es) => DslBuilderEffects h e r -> DslBuilderEffects h es r-useImplDslBuilderEffects = oneWayCoerce--runDslBuilderEffects :: h es -> DslBuilderEffects h es r -> Eff es r-runDslBuilderEffects h f = makeOp (unMkDslBuilderEffects f h)--dslBuilderEffects :: (forall e. h e -> Eff (e :& es) r) -> DslBuilderEffects h es r-dslBuilderEffects = MkDslBuilderEffects--instance-  (e <: es) =>-  OneWayCoercible (DslBuilderEffects h e r) (DslBuilderEffects h es r)-  where-  oneWayCoercibleImpl = oneWayCoercible--instance (Handle h) => Functor (DslBuilderEffects h es) where-  fmap f g =-    dslBuilderEffects $ \h ->-      fmap f (runDslBuilderEffects (mapHandle h) (useImplDslBuilderEffects g))--instance (Handle h) => Applicative (DslBuilderEffects h es) where-  pure x = dslBuilderEffects (pure (pure x))-  f <*> x = dslBuilderEffects $ \h ->-    runDslBuilderEffects (mapHandle h) (useImplDslBuilderEffects f)-      <*> runDslBuilderEffects (mapHandle h) (useImplDslBuilderEffects x)--instance (Handle h) => Monad (DslBuilderEffects h es) where-  m >>= f = dslBuilderEffects $ \h -> do-    r <- runDslBuilderEffects (mapHandle h) (useImplDslBuilderEffects m)-    runDslBuilderEffects (mapHandle h) (useImplDslBuilderEffects (f r))
src/Bluefin/Internal/Exception/Scoped.hs view
@@ -2,6 +2,7 @@   ( Exception,     InFlight,     try,+    localTry,     throw,     newException,     checkException,@@ -17,9 +18,13 @@ try :: (Exception e -> IO a) -> IO (Either e a) try k = do   ex <- newException+  localTry ex (k ex)++localTry :: Exception e -> IO a -> IO (Either e a)+localTry ex action =   tryJust     (checkException ex)-    (k ex)+    action  throw :: Exception e -> e -> IO a throw ex e = throwIO (MkInFlight ex e)
test/Main.hs view
@@ -19,6 +19,7 @@     test_runPureEffAsyncSafeReapsWorker,   ) import Test.SpecH (SpecH, assertEqual, runSpecH)+import Test.ThrowCatch (test_throwCatch) import Prelude hiding (break, read)  main :: IO ()@@ -81,6 +82,7 @@     test_localInHandler y     test_readerCleanup y     test_generalBracket io y+    test_throwCatch y     test_streamConsumeReader y     test_streamConsumeHandleReader y     test_unliftIOReader io y
+ test/Test/ThrowCatch.hs view
@@ -0,0 +1,29 @@+module Test.ThrowCatch where++import Bluefin.Internal+import Bluefin.Internal.Capability.ThrowCatch qualified as ThrowCatch+import Test.SpecH (SpecH, assertEqual)++test_throwCatch :: (e <: es) => SpecH e -> Eff es ()+test_throwCatch y = do+  assertEqual+    y+    "ThrowCatch.try catches a thrown exception"+    (Left @String @() "caught")+    (runPureEff (ThrowCatch.try $ \ex -> ThrowCatch.throw ex "caught"))+  assertEqual+    y+    "ThrowCatch.try returns a successful result"+    (Right @String @Int 42)+    (runPureEff (ThrowCatch.try $ \_ -> pure 42))+  assertEqual+    y+    "ThrowCatch.localTry catches a thrown exception"+    (Left @String @() "outer")+    ( runPureEff $ ThrowCatch.try $ \ex -> do+        localResult <- ThrowCatch.localTry ex (ThrowCatch.throw ex "inner")+        ThrowCatch.throw ex $ case localResult of+          Left "inner" -> "outer"+          Left _ -> "unexpected local exception"+          Right () -> "localTry did not catch"+    )