bluefin-internal 0.8.1.0 → 0.8.2.0
raw patch · 4 files changed
+26/−7 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−0
- bluefin-internal.cabal +1/−1
- src/Bluefin/Internal.hs +13/−5
- src/Bluefin/Internal/DslBuilderEff.hs +8/−1
CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.8.2.0++* Improve performance of `Reader` and `DslBuilderEff`+ # 0.8.1.0 * Add `trans3D`, `oneWayCoercibleNewtypeHandle`
bluefin-internal.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: bluefin-internal-version: 0.8.1.0+version: 0.8.2.0 license: MIT license-file: LICENSE author: Tom Ellis
src/Bluefin/Internal.hs view
@@ -38,9 +38,9 @@ import Control.Monad.Trans.Control (MonadBaseControl, StM, liftBaseWith, restoreM) import Control.Monad.Trans.Reader (ReaderT) import Control.Monad.Trans.Reader qualified as Reader-import Data.Coerce (coerce)+import Data.Coerce (Coercible, coerce) import Data.Foldable (for_)-import Data.IORef (IORef, modifyIORef, newIORef, readIORef, writeIORef)+import Data.IORef (IORef, modifyIORef', newIORef, readIORef, writeIORef) import Data.Kind (Type) import Data.Proxy (Proxy (Proxy)) import Data.Type.Coercion (Coercion (Coercion))@@ -49,7 +49,6 @@ import System.IO.Unsafe (unsafePerformIO) import Unsafe.Coerce (unsafeCoerce) import Prelude hiding (drop, head, read, return)-import Data.Coerce (Coercible) -- | Each inhabitant of @Effects@ is a set of effect tags, used for -- effect tracking to ensure that effects don't escape the scope of@@ -581,6 +580,15 @@ -- } +-- | For defining 'OneWayCoercible' instances for newtypes. Example:+--+-- @+-- newtype Random g e = Random (State g e)+-- deriving (Handle) via OneWayCoercibleHandle (Random g)+--+-- instance (e \<: es) => OneWayCoercible (Random g e) (Random g es) where+-- oneWayCoercibleImpl = oneWayCoercibleNewtypeHandle @(State g)+-- @ oneWayCoercibleNewtypeHandle :: forall h1 h2 e es. (e :> es) =>@@ -588,6 +596,7 @@ OneWayCoercible (h1 e) (h1 es), Coercible (h1 es) (h2 es) ) =>+ -- | ͘ OneWayCoercibleD (h2 e) (h2 es) oneWayCoercibleNewtypeHandle = trans3D@@ -1624,7 +1633,6 @@ tell (Writer y) = yield y type Reader :: Type -> Effects -> Type- newtype Reader r e = MkReader (Vault.Key r) deriving (Handle) via OneWayCoercibleHandle (Reader r) @@ -1641,7 +1649,7 @@ runReader r f = do k <- UnsafeMkEff $ \vault -> do k <- Vault.newKey- modifyIORef vault (\v -> Vault.insert k r v)+ modifyIORef' vault (\v -> Vault.insert k r v) pure k makeOp (f (MkReader k))
src/Bluefin/Internal/DslBuilderEff.hs view
@@ -10,6 +10,8 @@ oneWayCoercible, oneWayCoercibleImpl, )+import GHC.Base (oneShot)+import GHC.IO (IO (IO)) newtype DslBuilderEff h es r = MkDslBuilderEff {unMkDslBuilderEff :: forall e. h e -> Eff (e :& es) r}@@ -28,11 +30,16 @@ Eff es r runDslBuilderEff h f = makeOp (unMkDslBuilderEff f h) +-- oneShot is essential for good performance. I don't fully understand+-- why. dslBuilderEff :: (forall e. h e -> Eff (e :& es) r) -> -- | ͘ DslBuilderEff h es r-dslBuilderEff = MkDslBuilderEff+dslBuilderEff f = MkDslBuilderEff $ \h -> case f h of+ UnsafeMkEff g -> UnsafeMkEff $ oneShot $ \env -> case g env of+ -- Expose IO's state transformer so it too can be marked one-shot+ IO io -> IO (oneShot io) instance (e <: es) =>