packages feed

bluefin-internal 0.3.1.0 → 0.3.2.0

raw patch · 4 files changed

+305/−2 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Bluefin.Internal: instance (Bluefin.Internal.Handle h1, Bluefin.Internal.Handle h2) => Bluefin.Internal.Handle (h1 GHC.Generics.:*: h2)
+ Bluefin.Internal: instance Bluefin.Internal.Handle h => Bluefin.Internal.Handle (GHC.Generics.M1 i t h)
+ Bluefin.Internal: instance Bluefin.Internal.Handle h => Bluefin.Internal.Handle (GHC.Generics.Rec1 h)
+ Bluefin.Internal.CloneableHandle: MkArrow :: (forall (e :: Effects). () => h1 e -> h2 (e :& es)) -> (:~>) (h1 :: Effects -> Type) (h2 :: Effects -> Type) (es :: Effects)
+ Bluefin.Internal.CloneableHandle: MkCloneableHandleD :: (forall (e :: Effects). () => HandleCloner h h e) -> CloneableHandleD (h :: Effects -> Type)
+ Bluefin.Internal.CloneableHandle: MkGenericCloneableHandle :: h e -> GenericCloneableHandle (h :: k -> Type) (e :: k)
+ Bluefin.Internal.CloneableHandle: MkHandleCloner :: (forall r. () => h1 es -> (forall (e :: Effects). () => h2 e -> Eff (e :& es) r) -> Eff es r) -> HandleCloner (h1 :: Effects -> Type) (h2 :: Effects -> Type) (es :: Effects)
+ Bluefin.Internal.CloneableHandle: abstract :: forall h2 h1 (es :: Effects). Handle h2 => (forall (e :: Effects). () => h1 e -> h2 (e :& es)) -> (h1 :~> h2) es
+ Bluefin.Internal.CloneableHandle: apHC :: forall (h :: Effects -> Type) (h1 :: Effects -> Type) (h2 :: Effects -> Type) (e :: Effects). (Handle h, Handle h1, Handle h2) => HandleCloner h (h1 :~> h2) e -> HandleCloner h h1 e -> HandleCloner h h2 e
+ Bluefin.Internal.CloneableHandle: app :: forall h2 h1 (e :: Effects). Handle h2 => (h1 :~> h2) e -> h1 e -> h2 e
+ Bluefin.Internal.CloneableHandle: class Handle h => CloneableHandle (h :: Effects -> Type)
+ Bluefin.Internal.CloneableHandle: class Handle h => GCloneableHandle (h :: Effects -> Type)
+ Bluefin.Internal.CloneableHandle: class Generic1 (f :: k -> Type)
+ Bluefin.Internal.CloneableHandle: class Monad m => MonadIO (m :: Type -> Type)
+ Bluefin.Internal.CloneableHandle: class MonadIO m => MonadUnliftIO (m :: Type -> Type)
+ Bluefin.Internal.CloneableHandle: cloneHandle2 :: forall h1 h2 (e1 :: Effects) (es :: Effects) r. (Handle h1, Handle h2, e1 :> es) => HandleCloner h1 h2 es -> h1 e1 -> (forall (e :: Effects). () => h2 e -> Eff (e :& es) r) -> Eff es r
+ Bluefin.Internal.CloneableHandle: cloneHandleClass :: forall (e1 :: Effects) (es :: Effects) h r. (e1 :> es, CloneableHandle h) => h e1 -> (forall (e :: Effects). () => h e -> Eff (e :& es) r) -> Eff es r
+ Bluefin.Internal.CloneableHandle: cloneableHandleImpl :: CloneableHandle h => CloneableHandleD h
+ Bluefin.Internal.CloneableHandle: fmapHC :: forall (h :: Effects -> Type) (h1 :: Effects -> Type) (h2 :: Effects -> Type) (e :: Effects). (Handle h, Handle h1, Handle h2) => (h1 :~> h2) e -> HandleCloner h h1 e -> HandleCloner h h2 e
+ Bluefin.Internal.CloneableHandle: gCloneableHandle :: forall (h :: Effects -> Type). (Handle h, Generic1 h, GCloneableHandle (Rep1 h)) => CloneableHandleD h
+ Bluefin.Internal.CloneableHandle: gCloneableHandleImpl :: GCloneableHandle h => CloneableHandleD h
+ Bluefin.Internal.CloneableHandle: getHandleCloner :: forall (h :: Effects -> Type) (e :: Effects). GCloneableHandle h => HandleCloner h h e
+ Bluefin.Internal.CloneableHandle: hcException :: forall ex (e :: Effects). HandleCloner (Exception ex) (Exception ex) e
+ Bluefin.Internal.CloneableHandle: hcHandleReader :: forall (h :: Effects -> Type) (e :: Effects). CloneableHandle h => HandleCloner (HandleReader h) (HandleReader h) e
+ Bluefin.Internal.CloneableHandle: hcIOE :: forall (e :: Effects). HandleCloner IOE IOE e
+ Bluefin.Internal.CloneableHandle: hcReader :: forall r (e :: Effects). HandleCloner (Reader r) (Reader r) e
+ Bluefin.Internal.CloneableHandle: hcState :: forall s (e :: Effects). HandleCloner (State s) (State s) e
+ Bluefin.Internal.CloneableHandle: infixl 9 `apHC`
+ Bluefin.Internal.CloneableHandle: infixr 9 :~>
+ Bluefin.Internal.CloneableHandle: instance (Bluefin.Internal.CloneableHandle.GCloneableHandle h1, Bluefin.Internal.CloneableHandle.GCloneableHandle h2) => Bluefin.Internal.CloneableHandle.GCloneableHandle (h1 GHC.Generics.:*: h2)
+ Bluefin.Internal.CloneableHandle: instance (Bluefin.Internal.Handle h, GHC.Generics.Generic1 h, Bluefin.Internal.CloneableHandle.GCloneableHandle (GHC.Generics.Rep1 h)) => Bluefin.Internal.CloneableHandle.CloneableHandle (Bluefin.Internal.CloneableHandle.GenericCloneableHandle h)
+ Bluefin.Internal.CloneableHandle: instance (Bluefin.Internal.Handle h1, Bluefin.Internal.Handle h2) => Bluefin.Internal.Handle (Bluefin.Internal.CloneableHandle.HandleCloner h1 h2)
+ Bluefin.Internal.CloneableHandle: instance (Bluefin.Internal.Handle h1, Bluefin.Internal.Handle h2) => Bluefin.Internal.Handle (h1 Bluefin.Internal.CloneableHandle.:~> h2)
+ Bluefin.Internal.CloneableHandle: instance (Bluefin.Internal.Handle h1, Bluefin.Internal.Handle h2) => Bluefin.Internal.OneWayCoercible.OneWayCoercible ((Bluefin.Internal.CloneableHandle.:~>) h1 h2 e) ((Bluefin.Internal.CloneableHandle.:~>) h1 h2 es)
+ Bluefin.Internal.CloneableHandle: instance (Bluefin.Internal.Handle h1, Bluefin.Internal.Handle h2) => Bluefin.Internal.OneWayCoercible.OneWayCoercible (Bluefin.Internal.CloneableHandle.HandleCloner h1 h2 e) (Bluefin.Internal.CloneableHandle.HandleCloner h1 h2 es)
+ Bluefin.Internal.CloneableHandle: instance (TypeError ...) => Bluefin.Internal.CloneableHandle.CloneableHandle (Bluefin.Internal.Coroutine a b)
+ Bluefin.Internal.CloneableHandle: instance (TypeError ...) => Bluefin.Internal.CloneableHandle.CloneableHandle (Bluefin.Internal.Writer w)
+ Bluefin.Internal.CloneableHandle: instance Bluefin.Internal.CloneableHandle.CloneableHandle (Bluefin.Internal.Exception a)
+ Bluefin.Internal.CloneableHandle: instance Bluefin.Internal.CloneableHandle.CloneableHandle (Bluefin.Internal.Reader r)
+ Bluefin.Internal.CloneableHandle: instance Bluefin.Internal.CloneableHandle.CloneableHandle (Bluefin.Internal.State s)
+ Bluefin.Internal.CloneableHandle: instance Bluefin.Internal.CloneableHandle.CloneableHandle Bluefin.Internal.IOE
+ Bluefin.Internal.CloneableHandle: instance Bluefin.Internal.CloneableHandle.CloneableHandle h => Bluefin.Internal.CloneableHandle.CloneableHandle (Bluefin.Internal.HandleReader h)
+ Bluefin.Internal.CloneableHandle: instance Bluefin.Internal.CloneableHandle.CloneableHandle h => Bluefin.Internal.CloneableHandle.GCloneableHandle (GHC.Generics.Rec1 h)
+ Bluefin.Internal.CloneableHandle: instance Bluefin.Internal.CloneableHandle.GCloneableHandle h => Bluefin.Internal.CloneableHandle.GCloneableHandle (GHC.Generics.M1 i t h)
+ Bluefin.Internal.CloneableHandle: instance Bluefin.Internal.Handle h => Bluefin.Internal.Handle (Bluefin.Internal.CloneableHandle.GenericCloneableHandle h)
+ Bluefin.Internal.CloneableHandle: liftHC2 :: forall (h :: Effects -> Type) h1 h2 hr (es :: Effects). (Handle h, Handle h1, Handle h2) => (forall (e :: Effects). () => h1 e -> h2 e -> hr e) -> HandleCloner h h1 es -> HandleCloner h h2 es -> HandleCloner h hr es
+ Bluefin.Internal.CloneableHandle: liftIO :: MonadIO m => IO a -> m a
+ Bluefin.Internal.CloneableHandle: lmapHC :: forall (h :: Effects -> Type) (h2 :: Effects -> Type) (h1 :: Effects -> Type) (e :: Effects). (Handle h, Handle h2) => (h1 :~> h2) e -> HandleCloner h2 h e -> HandleCloner h1 h e
+ Bluefin.Internal.CloneableHandle: newtype ( (h1 :: Effects -> Type) :~> (h2 :: Effects -> Type) ) (es :: Effects)
+ Bluefin.Internal.CloneableHandle: newtype CloneableHandleD (h :: Effects -> Type)
+ Bluefin.Internal.CloneableHandle: newtype GenericCloneableHandle (h :: k -> Type) (e :: k)
+ Bluefin.Internal.CloneableHandle: newtype HandleCloner (h1 :: Effects -> Type) (h2 :: Effects -> Type) (es :: Effects)
+ Bluefin.Internal.CloneableHandle: pureHC :: forall h2 (e :: Effects) (h1 :: Effects -> Type). h2 e -> HandleCloner h1 h2 e
+ Bluefin.Internal.CloneableHandle: withEffToIOCloneHandle :: forall (e1 :: Effects) (es :: Effects) h a. (e1 :> es, CloneableHandle h) => IOE e1 -> h es -> ((forall r. () => (forall (e :: Effects). () => IOE e -> h e -> Eff e r) -> IO r) -> IO a) -> Eff es a
+ Bluefin.Internal.CloneableHandle: withRunInIO :: MonadUnliftIO m => ((forall a. () => m a -> IO a) -> IO b) -> m b

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+# 0.3.2.0++* Add `Bluefin.Internal.CloneHandle`+ # 0.3.1.0  * Add `Bluefin.Internal.DslBuilder`
bluefin-internal.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               bluefin-internal-version:            0.3.1.0+version:            0.3.2.0 license:            MIT license-file:       LICENSE author:             Tom Ellis@@ -83,6 +83,7 @@       monad-control < 1.1     exposed-modules:       Bluefin.Internal,+      Bluefin.Internal.CloneableHandle,       Bluefin.Internal.DslBuilder,       Bluefin.Internal.DslBuilderEffects,       Bluefin.Internal.Examples,
src/Bluefin/Internal.hs view
@@ -38,7 +38,7 @@ import Data.Proxy (Proxy (Proxy)) import Data.Type.Coercion (Coercion (Coercion)) import GHC.Exts (Proxy#, proxy#)-import GHC.Generics (Generic)+import GHC.Generics (Generic, M1 (M1), Rec1 (Rec1), (:*:) ((:*:))) import System.IO.Unsafe (unsafePerformIO) import Unsafe.Coerce (unsafeCoerce) import Prelude hiding (drop, head, read, return)@@ -464,6 +464,15 @@   -- | ͘   HandleD h handleOneWayCoercion owc = MkHandleD (oneWayCoerceWith owc)++instance (Handle h) => Handle (Rec1 h) where+  handleImpl = handleMapHandle $ \(Rec1 h) -> Rec1 (mapHandle h)++instance (Handle h) => Handle (M1 i t h) where+  handleImpl = handleMapHandle $ \(M1 h) -> M1 (mapHandle h)++instance (Handle h1, Handle h2) => Handle (h1 :*: h2) where+  handleImpl = handleMapHandle $ \(h1 :*: h2) -> mapHandle h1 :*: mapHandle h2  -- { OneWayCoercibleHandle 
+ src/Bluefin/Internal/CloneableHandle.hs view
@@ -0,0 +1,289 @@+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE QuantifiedConstraints #-}+{-# LANGUAGE UndecidableInstances #-}++module Bluefin.Internal.CloneableHandle+  ( module Bluefin.Internal.CloneableHandle,+    MonadUnliftIO (withRunInIO),+    MonadIO (liftIO),+    Generic1,+  )+where++import Bluefin.Internal hiding (b, race, w)+import Bluefin.Internal.OneWayCoercible+  ( OneWayCoercible (..),+    unsafeOneWayCoercible,+  )+import Control.Monad.IO.Unlift (MonadIO (liftIO), MonadUnliftIO (withRunInIO))+import Data.Coerce (coerce)+import GHC.Generics+  ( Generic1 (..),+    M1 (M1),+    Rec1 (Rec1),+    (:*:) ((:*:)),+  )+import GHC.TypeLits (ErrorMessage (Text), TypeError)++withEffToIOCloneHandle ::+  (e1 :> es, CloneableHandle h) =>+  IOE e1 ->+  -- | Handle accessible in the continuation+  h es ->+  -- | Continuation with the unlifting function in scope.+  ((forall r. (forall e. IOE e -> h e -> Eff e r) -> IO r) -> IO a) ->+  Eff es a+withEffToIOCloneHandle io h k = do+  withEffToIO_ io $ \runInIO -> do+    k $ \body -> do+      runInIO $ do+        cloneHandleClass h $ \h' -> do+          cloneHandleClass io $ \io' -> do+            body (mapHandle io') (mapHandle h')++newtype HandleCloner h1 h2 es+  = MkHandleCloner+      ( forall r.+        h1 es ->+        (forall e. h2 e -> Eff (e :& es) r) ->+        Eff es r+      )++instance (Handle h1, Handle h2) => Handle (HandleCloner h1 h2) where+  handleImpl = handleOneWayCoercible++instance+  (Handle h1, Handle h2) =>+  OneWayCoercible+    (HandleCloner h1 h2 e)+    (HandleCloner h1 h2 es)+  where+  -- FIXME: These instances for higher rank types are annoying+  oneWayCoercibleImpl = unsafeOneWayCoercible++cloneHandle2 ::+  (Handle h1, Handle h2, e1 :> es) =>+  HandleCloner h1 h2 es ->+  h1 e1 ->+  (forall e. h2 e -> Eff (e :& es) r) ->+  Eff es r+cloneHandle2 (MkHandleCloner c) h1 = c (mapHandle h1)++instance CloneableHandle IOE where+  cloneableHandleImpl = MkCloneableHandleD hcIOE++hcIOE :: HandleCloner IOE IOE e+hcIOE = MkHandleCloner $ \io k -> do+  useImplIn k (mapHandle io)++-- | Cloning a @State@ copies its contents to a new @State@.  Changes+-- to one will not effect the other.+instance CloneableHandle (State s) where+  cloneableHandleImpl = MkCloneableHandleD hcState++hcState :: HandleCloner (State s) (State s) e+hcState = MkHandleCloner $ \st k -> do+  s <- get st+  evalState s $ \st' ->+    useImplIn k (mapHandle st')++instance CloneableHandle (Exception a) where+  cloneableHandleImpl = MkCloneableHandleD hcException++hcException :: HandleCloner (Exception ex) (Exception ex) e+hcException = MkHandleCloner $ \ex k -> do+  useImplIn k (mapHandle ex)++instance CloneableHandle (Reader r) where+  cloneableHandleImpl = MkCloneableHandleD hcReader++hcReader :: HandleCloner (Reader r) (Reader r) e+hcReader = MkHandleCloner $ \(MkReader s) k -> do+  cloneHandleClass s $ \s' -> do+    useImplIn k (MkReader (mapHandle s'))++-- | Cloning a @HandleReader@ copies its contents to a new+-- @HandleReader@.  Changes to one will not effect the other.+instance (CloneableHandle h) => CloneableHandle (HandleReader h) where+  cloneableHandleImpl = MkCloneableHandleD hcHandleReader++cloneHandleClass ::+  (e1 :> es, CloneableHandle h) =>+  h e1 ->+  (forall e. h e -> Eff (e :& es) r) ->+  Eff es r+cloneHandleClass =+  cloneHandle2 (case cloneableHandleImpl of MkCloneableHandleD c' -> c')++hcHandleReader :: (CloneableHandle h) => HandleCloner (HandleReader h) (HandleReader h) e+hcHandleReader = MkHandleCloner $ \hr k -> do+  h <- askHandle hr+  cloneHandleClass h $ \h' -> do+    runHandleReader h' $ \hr' -> do+      useImplIn k (mapHandle hr')++instance+  (TypeError (Text "Coroutine cannot be cloned. Perhaps you want an STM channel?")) =>+  CloneableHandle (Coroutine a b)+  where+  cloneableHandleImpl =+    error "instance CloneableHandle (Coroutine a b) not implemented"++instance+  (TypeError (Text "Writer cannot be cloned. Perhaps you want an STM channel?")) =>+  CloneableHandle (Writer w)+  where+  cloneableHandleImpl =+    error "instance CloneableHandle (Writer a) not implemented"++newtype (h1 :~> h2) es = MkArrow (forall e. h1 e -> h2 (e :& es))++instance (Handle h1, Handle h2) => Handle (h1 :~> h2) where+  handleImpl = handleOneWayCoercible++instance+  (Handle h1, Handle h2) =>+  OneWayCoercible+    ((h1 :~> h2) e)+    ((h1 :~> h2) es)+  where+  -- FIXME: These instances for higher rank types are annoying+  oneWayCoercibleImpl = unsafeOneWayCoercible++abstract :: (Handle h2) => (forall e. h1 e -> h2 (e :& es)) -> (h1 :~> h2) es+abstract k = MkArrow (mapHandle . k)++app ::+  (Handle h2) =>+  (h1 :~> h2) e ->+  h1 e ->+  h2 e+app (MkArrow f) h1 = makeOpHandle (f h1)+  where+    makeOpHandle :: forall h e. (Handle h) => h (e :& e) -> h e+    makeOpHandle = case have @(e :& e) @e (subsume1 (eq ZW)) of+      Dict -> mapHandle++lmapHC ::+  (Handle h, Handle h2) =>+  (h1 :~> h2) e ->+  HandleCloner h2 h e ->+  HandleCloner h1 h e+lmapHC f hc = MkHandleCloner $ \h1 k1 -> cloneHandle2 hc (app f h1) k1++pureHC :: h2 e -> HandleCloner h1 h2 e+pureHC h2 = MkHandleCloner $ \_ k -> makeOp (k h2)++fmapHC ::+  (Handle h, Handle h1, Handle h2) =>+  (h1 :~> h2) e ->+  HandleCloner h h1 e ->+  HandleCloner h h2 e+fmapHC f h = pureHC f `apHC` h++apHC ::+  (Handle h, Handle h1, Handle h2) =>+  HandleCloner h (h1 :~> h2) e ->+  HandleCloner h h1 e ->+  HandleCloner h h2 e+apHC cf c1 = MkHandleCloner $ \h k2 -> do+  cloneHandle2 (mapHandle cf) h $ \hf -> do+    cloneHandle2 (mapHandle c1) h $ \h1 -> do+      useImplIn k2 (app (mapHandle hf) (mapHandle h1))++liftHC2 ::+  forall h h1 h2 hr es.+  (Handle h, Handle h1, Handle h2) =>+  (forall e. h1 e -> h2 e -> hr e) ->+  HandleCloner h h1 es ->+  HandleCloner h h2 es ->+  HandleCloner h hr es+liftHC2 f c1 c2 = MkHandleCloner $ \h kr -> do+  cloneHandle2 c1 h $ \h1 -> do+    cloneHandle2 (mapHandle c2) h $ \h2 -> do+      useImplIn kr (f (mapHandle h1) (mapHandle h2))++infixr 9 :~>++infixl 9 `apHC`++-- | You can use @DerivingVia@ with @GenericCloneableHandle@ to derive+-- a 'CloneableHandle' instance for your type, as long as it is a+-- product type of @CloneableHandle@s.+newtype GenericCloneableHandle h e = MkGenericCloneableHandle (h e)++instance (Handle h) => Handle (GenericCloneableHandle h) where+  handleImpl = handleMapHandle $ \(MkGenericCloneableHandle h) ->+    MkGenericCloneableHandle (mapHandle h)++instance+  (Handle h, Generic1 h, GCloneableHandle (Rep1 h)) =>+  CloneableHandle (GenericCloneableHandle h)+  where+  cloneableHandleImpl = coerce (gCloneableHandle @h)++newtype CloneableHandleD h = MkCloneableHandleD (forall e. HandleCloner h h e)++getHandleCloner :: (GCloneableHandle h) => HandleCloner h h e+getHandleCloner = case gCloneableHandleImpl of MkCloneableHandleD c -> c++gCloneableHandle ::+  forall h.+  (Handle h, Generic1 h) =>+  (GCloneableHandle (Rep1 h)) =>+  CloneableHandleD h+gCloneableHandle =+  MkCloneableHandleD+    ( fmapHC+        (abstract (mapHandle . to1))+        (lmapHC (abstract (mapHandle . from1)) getHandleCloner)+    )++-- | You can define a @CloneableHandle@ instance for your @Handle@ as+-- long as it is a product type of @CloneableHandle@s.  To define the+-- instance, use @DerivingVia@ and 'GenericCloneableHandle'.  For+-- example:+--+-- @+-- data MyHandle e = MkMyHandle ('Bluefin.Exception.Exception' String e) ('Bluefin.State.State' Int e)+--   deriving ('Bluefin.Compound.Generic', 'Generic1')+--   deriving ('Bluefin.Compound.Handle') via t'Bluefin.Compound.OneWayCoercibleHandle' MyHandle+--   deriving ('CloneableHandle') via 'GenericCloneableHandle' MyHandle+--+-- instance (e t'Bluefin.Eff.:>' es) => t'Bluefin.Compound.OneWayCoercible' (MyHandle e) (MyHandle es) where+--   'Bluefin.Compound.oneWayCoercibleImpl' = 'Bluefin.Compound.gOneWayCoercible'+-- @+class (Handle h) => CloneableHandle h where+  -- | Blah+  cloneableHandleImpl :: CloneableHandleD h++-- | @Generic@ implementation detail of+-- 'GenericCloneableHandle'. Bluefin users should never need to use+-- this directly.+class (Handle h) => GCloneableHandle h where+  gCloneableHandleImpl :: CloneableHandleD h++-- | A cloneable handle is generically cloneable+instance+  (CloneableHandle h) =>+  GCloneableHandle (Rec1 h)+  where+  gCloneableHandleImpl = coerce (cloneableHandleImpl @h)++-- | An annotated cloneable handle is generically cloneable+instance+  (GCloneableHandle h) =>+  GCloneableHandle (M1 i t h)+  where+  gCloneableHandleImpl = coerce (gCloneableHandleImpl @h)++-- | A pair of cloneable handles is generically cloneable+instance+  (GCloneableHandle h1, GCloneableHandle h2) =>+  GCloneableHandle (h1 :*: h2)+  where+  gCloneableHandleImpl =+    MkCloneableHandleD $+      (abstract $ \h1 -> abstract $ \h2 -> mapHandle h1 :*: mapHandle h2)+        `fmapHC` lmapHC (abstract $ \(h1 :*: _) -> mapHandle h1) getHandleCloner+        `apHC` lmapHC (abstract $ \(_ :*: h2) -> mapHandle h2) getHandleCloner