bluefin-internal-0.5.0.0: The Bluefin effect system, internals
Safe HaskellNone
LanguageHaskell2010

Bluefin.Internal.GadtEffect

Synopsis

Documentation

newtype Send (f :: Effect) (e :: Effects) Source #

Bring a Send into scope with interpret.

Constructors

MkSend (EffectHandler f e) 

Instances

Instances details
e :> es => OneWayCoercible (Send f e :: Type) (Send f es :: Type) Source # 
Instance details

Defined in Bluefin.Internal.GadtEffect

Handle (Send f) Source # 
Instance details

Defined in Bluefin.Internal.GadtEffect

type Effect = (Type -> Type) -> Type -> Type Source #

A convenient type synoynm matching effectful and polysemy's usages provided for people who are migrating from those libraries.

send Source #

Arguments

:: forall (e1 :: Effects) (es :: Effects) f r. e1 :> es 
=> Send f e1 
-> f (Eff es) r

Handle this operation using the effect handler currently in scope for the Send f handle.

-> Eff es r 

Send a primitive operation to the handler for interpretation. This is the Bluefin analog of effectful's send and polysemy's send.

type EffectHandler (f :: (Type -> Type) -> Type -> Type) (es :: Effects) Source #

Arguments

 = forall (e :: Effects) r. f (Eff e) r 
-> Eff (e :& es) r

͘

A convenient type synonym. This is like effectful's EffectHandler. A similar type also appears in polysemy as the argument to functions like intercept.

interpret Source #

Arguments

:: forall (f :: (Type -> Type) -> Type -> Type) (es :: Effects) r. EffectHandler f es

Implementation of effect handler for Send f

-> (forall (e :: Effects). Send f e -> Eff (e :& es) r)

Within this block, send has the implementation given above.

-> Eff es r 
import System.IO qualified as IO

runFileSystem ::
  forall es e1 e2 r.
  (e1 :> es, e2 :> es) =>
  IOE e1 ->
  Exception IOException e2 ->
  (forall e. Send FileSystem e -> Eff (e :& es) r) ->
  Eff es r
runFileSystem io ex = interpret $ \case
  ReadFile path ->
    adapt (IO.readFile path)
  WriteFile path contents ->
    adapt (IO.writeFile path contents)
  Trace msg body -> do
    effIO io (putStrLn ("Start: " <> msg))
    r <- useImpl body
    effIO io (putStrLn ("End: " <> msg))
    pure r
  where
    -- If you don't want to write this signature you can use
    -- {-# LANGUAGE NoMonoLocalBinds #-}
    adapt :: (e1 :> es', e2 :> es') => IO r' -> Eff es' r'
    adapt m = rethrowIO io ex (effIO io m)

newtype GadtEffect (f :: (Type -> Type) -> Type -> Type) a (e :: Effects) Source #

Constructors

MkGadtEffect 

Fields

mapGadtEffect :: forall f1 (e1 :: Effects) r1 f2 (e2 :: Effects) r2. (f1 (Eff e1) r1 -> f2 (Eff e2) r2) -> GadtEffect f1 r1 e1 -> GadtEffect f2 r2 e2 Source #

oneWayCoercibleGadtEffectTrustMe Source #

Arguments

:: forall (e :: Effects) (es :: Effects) f r. e :> es 
=> (forall (e' :: Effects) (es' :: Effects). e' :> es' => f (Eff e') r -> f (Eff es') r) 
-> OneWayCoercibleD (GadtEffect f r e) (GadtEffect f r es)

͘

instance
  (e :> es) =>
  OneWayCoercible (GadtEffect FileSystem r e) (GadtEffect FileSystem r es)
  where
  oneWayCoercibleImpl = oneWayCoercibleGadtEffectTrustMe $ \case
    ReadFile path -> ReadFile path
    WriteFile path contents -> WriteFile path contents
    Trace msg body -> Trace msg (useImpl body)

passthrough Source #

Arguments

:: forall f r (e1 :: Effects) (es :: Effects) (e2 :: Effects). (Handle (GadtEffect f r), e1 :> es, e2 :> es) 
=> Send f e1 
-> f (Eff e2) r 
-> Eff es r

͘

Version of send for use when pattern matching in interpose

augmentOp2Interpose ::
  (e1 :> es, e2 :> es) =>
  IOE e2 ->
  HandleReader (Send E) e1 ->
  Eff es r ->
  Eff es r
augmentOp2Interpose io = interpose $ \fc -> \case
  Op2 -> effIO io (putStrLn "augmented op2") >> send fc Op2
  op -> passthrough fc op

interpose Source #

Arguments

:: forall (e1 :: Effects) (es :: Effects) (f :: Effect) r. e1 :> es 
=> (Send f es -> EffectHandler f es)

Reimplementation of effect handler for Send f in terms of the the original effect handler, which is passed as the argument

-> HandleReader (Send f) e1

Original effect handler

-> Eff es r

Within this block, send has the implementation given above.

-> Eff es r 
augmentOp2Interpose ::
  (e1 :> es, e2 :> es) =>
  IOE e2 ->
  HandleReader (Send E) e1 ->
  Eff es r ->
  Eff es r
augmentOp2Interpose io = interpose $ \fc -> \case
  Op2 -> effIO io (putStrLn "augmented op2") >> send fc Op2
  op -> passthrough fc op