| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Bluefin.CloneableHandle
Description
Bluefin.CloneableHandle defines the CloneableHandle class,
whose purpose is to support withEffToIOCloneHandle.
Synopsis
- 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
- class Handle h => CloneableHandle (h :: Effects -> Type)
- newtype GenericCloneableHandle (h :: k -> Type) (e :: k) = MkGenericCloneableHandle (h e)
- class Handle h => GCloneableHandle (h :: Effects -> Type)
- class Generic1 (f :: k -> Type)
Documentation
withEffToIOCloneHandle is an IO unlifting function that
clones its handle each time it runs Eff in IO. This is
convenient when the unlifting function is being used to fork
threads, since Bluefin state is not threadsafe. Be careful
when you use it, because it can be used to throw away the
effect tag on a Bluefin Eff action due to this part of
its type (here throwing away e):
(forall e. IOE e -> h e -> Eff e r) -> IO r
It is only safely used when you do not allow any effects to
escape their scope, so we suggest that you use it sparingly to
define reusable combinators which themselves are safe. For
example, here is how you could write an equivalent of async's
race primitive:
bluefinRace :: (CloneableHandleh, e1 :> es) =>IOEe1 -> h es -> (forall e. IOE e -> h e ->Effe r) -> (forall e. IOE e -> h e -> Eff e r) -> Eff es r bluefinRace io h m1 m2 = withEffToIOCloneHandle io h $ \runInIO -> do either id id <$> Control.Concurrent.Async.race (runInIO $ \io' h' -> m1 io' h') (runInIO $ \io' h' -> m2 io' h')
Then you can safely use it to race Bluefin Eff actions:
example :: IO () example =runEff_$ \io ->evalState0 $ \st -> do r <-try$ \ex -> do bluefinRace io (MkMyHandle (mapHandleex) (mapHandle st)) ( \_ (MkMyHandle ex' st') -> domodifyst' (subtract 2000)throwex' "Aborting from branch 1" ) ( \_ (MkMyHandle _ st') -> do modify st' (+ 3000) pure (2 :: Int) ) s <-getsteffIOio (print r) effIO io (putStrLn ("State started at 0 and was cloned. Now: " <> show s))
You can see from the output that the actions were raced as
expected, and the State was cloned so that changes to it in
the branches of race did not affect the original State.
-- Run one time (the first thread was faster) ghci> example Right 2 State started at 0 and was cloned. Now: 0 -- Run another time (the second thread was faster) ghci> example Left "Aborting from branch 1" State started at 0 and was cloned. Now: 0
Note that withEffToIOCloneHandle only allows access to one
external Handle within it, so if you have several you'd like
to use you'll have to define a new handle that bundles them
together.
CloneableHandle
class Handle h => CloneableHandle (h :: Effects -> Type) #
You can define a CloneableHandle instance for your Handle as
long as it is a product type of CloneableHandles. To define the
instance, use DerivingVia and GenericCloneableHandle. For
example:
data MyHandle e = MkMyHandle (ExceptionString e) (StateInt e) deriving (Generic,Generic1) deriving (Handle) viaOneWayCoercibleHandleMyHandle deriving (CloneableHandle) viaGenericCloneableHandleMyHandle instance (e:>es) =>OneWayCoercible(MyHandle e) (MyHandle es) whereoneWayCoercibleImpl=gOneWayCoercible
Minimal complete definition
Instances
newtype GenericCloneableHandle (h :: k -> Type) (e :: k) #
You can use DerivingVia with GenericCloneableHandle to derive
a CloneableHandle instance for your type, as long as it is a
product type of CloneableHandles.
Constructors
| MkGenericCloneableHandle (h e) |
Instances
| (Handle h, e :> es) => OneWayCoercible (GenericCloneableHandle h e :: Type) (GenericCloneableHandle h es :: Type) | |
Defined in Bluefin.Internal.CloneableHandle Methods oneWayCoercibleImpl :: OneWayCoercibleD (GenericCloneableHandle h e) (GenericCloneableHandle h es) # | |
| Handle h => Handle (GenericCloneableHandle h) | |
Defined in Bluefin.Internal.CloneableHandle Methods handleImpl :: HandleD (GenericCloneableHandle h) # | |
| (Handle h, Generic1 h, GCloneableHandle (Rep1 h)) => CloneableHandle (GenericCloneableHandle h) | |
Defined in Bluefin.Internal.CloneableHandle Methods cloneableHandleImpl :: CloneableHandleD (GenericCloneableHandle h) # | |
class Handle h => GCloneableHandle (h :: Effects -> Type) #
Generic implementation detail of
GenericCloneableHandle. Bluefin users should never need to use
this directly.
Minimal complete definition
Instances
| CloneableHandle h => GCloneableHandle (Rec1 h) | A cloneable handle is generically cloneable |
Defined in Bluefin.Internal.CloneableHandle Methods | |
| (GCloneableHandle h1, GCloneableHandle h2) => GCloneableHandle (h1 :*: h2) | A pair of cloneable handles is generically cloneable |
Defined in Bluefin.Internal.CloneableHandle Methods gCloneableHandleImpl :: CloneableHandleD (h1 :*: h2) # | |
| GCloneableHandle h => GCloneableHandle (M1 i t h) | An annotated cloneable handle is generically cloneable |
Defined in Bluefin.Internal.CloneableHandle Methods gCloneableHandleImpl :: CloneableHandleD (M1 i t h) # | |
GHC.Generics re-exports
class Generic1 (f :: k -> Type) #
Representable types of kind * -> * (or kind k -> *, when PolyKinds
is enabled).
This class is derivable in GHC with the DeriveGeneric flag on.
A Generic1 instance must satisfy the following laws:
from1.to1≡idto1.from1≡id
Instances
| Generic1 Down | |
| Generic1 NonEmpty | |
| Generic1 Par1 | |
| Generic1 Maybe | |
| Generic1 Solo | |
| Generic1 List | |
| Generic1 (Either a :: Type -> Type) | |
| Generic1 ((,) a :: Type -> Type) | |
| Generic1 (Proxy :: k -> Type) | |
| Generic1 (U1 :: k -> Type) | |
| Generic1 (V1 :: k -> Type) | |
| Generic1 ((,,) a b :: Type -> Type) | |
| Generic1 (Rec1 f :: k -> Type) | |
| Generic1 (URec (Ptr ()) :: k -> Type) | |
| Generic1 (URec Char :: k -> Type) | |
| Generic1 (URec Double :: k -> Type) | |
| Generic1 (URec Float :: k -> Type) | |
| Generic1 (URec Int :: k -> Type) | |
| Generic1 (URec Word :: k -> Type) | |
| Generic1 ((,,,) a b c :: Type -> Type) | |
| Generic1 (f :*: g :: k -> Type) | |
| Generic1 (f :+: g :: k -> Type) | |
| Generic1 (K1 i c :: k -> Type) | |
| Generic1 ((,,,,) a b c d :: Type -> Type) | |
| Functor f => Generic1 (f :.: g :: k -> Type) | |
| Generic1 (M1 i c f :: k -> Type) | |
| Generic1 ((,,,,,) a b c d e :: Type -> Type) | |
| Generic1 ((,,,,,,) a b c d e f :: Type -> Type) | |
| Generic1 ((,,,,,,,) a b c d e f g :: Type -> Type) | |
| Generic1 ((,,,,,,,,) a b c d e f g h :: Type -> Type) | |
Defined in GHC.Generics Associated Types type Rep1 ((,,,,,,,,) a b c d e f g h) :: k -> Type # Methods from1 :: forall (a0 :: k). (a, b, c, d, e, f, g, h, a0) -> Rep1 ((,,,,,,,,) a b c d e f g h) a0 # to1 :: forall (a0 :: k). Rep1 ((,,,,,,,,) a b c d e f g h) a0 -> (a, b, c, d, e, f, g, h, a0) # | |
| Generic1 ((,,,,,,,,,) a b c d e f g h i :: Type -> Type) | |
Defined in GHC.Generics Associated Types type Rep1 ((,,,,,,,,,) a b c d e f g h i) :: k -> Type # Methods from1 :: forall (a0 :: k). (a, b, c, d, e, f, g, h, i, a0) -> Rep1 ((,,,,,,,,,) a b c d e f g h i) a0 # to1 :: forall (a0 :: k). Rep1 ((,,,,,,,,,) a b c d e f g h i) a0 -> (a, b, c, d, e, f, g, h, i, a0) # | |
| Generic1 ((,,,,,,,,,,) a b c d e f g h i j :: Type -> Type) | |
Defined in GHC.Generics Associated Types type Rep1 ((,,,,,,,,,,) a b c d e f g h i j) :: k -> Type # Methods from1 :: forall (a0 :: k). (a, b, c, d, e, f, g, h, i, j, a0) -> Rep1 ((,,,,,,,,,,) a b c d e f g h i j) a0 # to1 :: forall (a0 :: k). Rep1 ((,,,,,,,,,,) a b c d e f g h i j) a0 -> (a, b, c, d, e, f, g, h, i, j, a0) # | |
| Generic1 ((,,,,,,,,,,,) a b c d e f g h i j k :: Type -> Type) | |
Defined in GHC.Generics Associated Types type Rep1 ((,,,,,,,,,,,) a b c d e f g h i j k) :: k -> Type # Methods from1 :: forall (a0 :: k0). (a, b, c, d, e, f, g, h, i, j, k, a0) -> Rep1 ((,,,,,,,,,,,) a b c d e f g h i j k) a0 # to1 :: forall (a0 :: k0). Rep1 ((,,,,,,,,,,,) a b c d e f g h i j k) a0 -> (a, b, c, d, e, f, g, h, i, j, k, a0) # | |
| Generic1 ((,,,,,,,,,,,,) a b c d e f g h i j k l :: Type -> Type) | |
Defined in GHC.Generics Associated Types type Rep1 ((,,,,,,,,,,,,) a b c d e f g h i j k l) :: k -> Type # Methods from1 :: forall (a0 :: k0). (a, b, c, d, e, f, g, h, i, j, k, l, a0) -> Rep1 ((,,,,,,,,,,,,) a b c d e f g h i j k l) a0 # to1 :: forall (a0 :: k0). Rep1 ((,,,,,,,,,,,,) a b c d e f g h i j k l) a0 -> (a, b, c, d, e, f, g, h, i, j, k, l, a0) # | |
| Generic1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m :: Type -> Type) | |
Defined in GHC.Generics Associated Types type Rep1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m) :: k -> Type # Methods from1 :: forall (a0 :: k0). (a, b, c, d, e, f, g, h, i, j, k, l, m, a0) -> Rep1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m) a0 # to1 :: forall (a0 :: k0). Rep1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m) a0 -> (a, b, c, d, e, f, g, h, i, j, k, l, m, a0) # | |
| Generic1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n :: Type -> Type) | |
Defined in GHC.Generics Associated Types type Rep1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n) :: k -> Type # Methods from1 :: forall (a0 :: k0). (a, b, c, d, e, f, g, h, i, j, k, l, m, n, a0) -> Rep1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n) a0 # to1 :: forall (a0 :: k0). Rep1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n) a0 -> (a, b, c, d, e, f, g, h, i, j, k, l, m, n, a0) # | |