Some docs

This commit is contained in:
Tom Ellis 2024-09-08 18:11:17 +01:00
parent 97cd74b199
commit caa59700d9

View File

@ -12,66 +12,28 @@ import Effectful.Internal.Env
import qualified Effectful.Internal.Monad as Effectful
import qualified Effectful.State.Dynamic as St
newtype Effectful es (e :: Effects) = MkEffectful (Env es)
-- * Bluefin handle
-- | Provide access to Effectful operations in Bluefin
newtype Effectful (es' :: [EffectfulEffect]) (e :: Effects)
= MkEffectful (Env es')
-- * Effectful effect
-- | Provide access to Bluefin operations in Effectful
data Bluefin es m a
-- * Type synonyms
type instance DispatchOf (Bluefin es) = Dynamic
voidBluefin :: Bluefin es m a -> r
voidBluefin = \case {}
type EffectfulEff = Effectful.Eff
useEffectful ::
(e :> es) =>
-- | Bluefin handle to @effectful@ operations
Effectful effes e ->
-- | An @effectful@ operation
Effectful.Eff effes r ->
Eff es r
useEffectful e k =
fromEffectful (\Proxy -> Effectful.inject k) e
type EffectfulEffect = Effectful.Effect
useBluefin ::
forall es effes r.
(Bluefin es Effectful.:> effes) =>
Eff es r ->
Effectful.Eff effes r
useBluefin m =
toEffectful (\(_ :: Effectful effes e) -> useImpl @es @(e :& es) m)
type a ::> b = a Effectful.:> b
toEffectful ::
forall es effes a.
(Bluefin es Effectful.:> effes) =>
(forall e. Effectful effes e -> Eff (e :& es) a) ->
Effectful.Eff effes a
toEffectful = unsafeToEffectful
unsafeInterpretBluefin ::
Effectful.Eff (Bluefin es : effes) a -> Effectful.Eff effes a
unsafeInterpretBluefin = Effectful.interpret (\_ -> voidBluefin)
fromEffectful ::
(e :> es) =>
(Proxy es -> Effectful.Eff (Bluefin es : effes) r) ->
Effectful effes e ->
Eff es r
fromEffectful m (MkEffectful env) =
UnsafeMkEff (Effectful.unEff (unsafeInterpretBluefin (m Proxy)) env)
unsafeToEffectful :: (Effectful es e -> Eff es' a) -> Effectful.Eff es a
unsafeToEffectful m =
Effectful.unsafeEff (\env' -> unsafeUnEff (m (MkEffectful env')))
handleWith ::
(e1 :> es) =>
-- | An @effectful@ handler
(Effectful.Eff (effe : effes) r1 -> Effectful.Eff effes r2) ->
-- | An @effectful@ operation, in Bluefin style
(forall e. Effectful (effe : effes) e -> Eff (e :& es) r1) ->
Effectful effes e1 ->
Eff es r2
handleWith handler m (MkEffectful env) =
UnsafeMkEff (Effectful.unEff (handler (unsafeToEffectful m)) env)
-- * Bluefin handlers
runEffectful ::
(e1 :> es) =>
@ -87,26 +49,86 @@ runPureEffectful ::
Eff es r
runPureEffectful k = pure (Effectful.runPureEff (unsafeToEffectful k))
handleWith ::
(e1 :> es) =>
-- | An @effectful@ handler
(EffectfulEff (e' : es') r1 -> EffectfulEff es' r2) ->
-- | An @effectful@ operation, in Bluefin style
(forall e. Effectful (e' : es') e -> Eff (e :& es) r1) ->
Effectful es' e1 ->
-- | The result of handling the @effectful@ operation in Bluefin
-- style using the @effectful@ handler
Eff es r2
handleWith handler m (MkEffectful env) =
UnsafeMkEff (Effectful.unEff (handler (unsafeToEffectful m)) env)
-- * Effectful handlers
runBluefin ::
Effectful.IOE Effectful.:> effes =>
(forall e es. IOE e -> Effectful.Eff (Bluefin (e :& es) : effes) r) ->
Effectful.Eff effes r
(Effectful.IOE ::> es') =>
-- | A Bluefin operation, in Effectful style (with IO)
(forall e es. IOE e -> EffectfulEff (Bluefin (e :& es) : es') r) ->
EffectfulEff es' r
runBluefin m = unsafeInterpretBluefin (m MkIOE)
runPureBluefin ::
(forall es. Effectful.Eff (Bluefin es : effes) r) ->
Effectful.Eff effes r
-- | A Bluefin operation, in Effectful style (without IO)
(forall es. EffectfulEff (Bluefin es : es') r) ->
EffectfulEff es' r
runPureBluefin = unsafeInterpretBluefin
-- * Use Bluefin operations in @effectful@ and vice versa
useEffectful ::
(e :> es) =>
-- | Bluefin handle to @effectful@ operations
Effectful es' e ->
-- | An @effectful@ operation
EffectfulEff es' r ->
Eff es r
useEffectful e k =
fromEffectful (\Proxy -> Effectful.inject k) e
useBluefin ::
forall es es' r.
(Bluefin es ::> es') =>
Eff es r ->
-- | ͘
EffectfulEff es' r
useBluefin m =
toEffectful (\(_ :: Effectful es' e) -> useImpl @es @(e :& es) m)
-- * Conversion between @effectful@ and Bluefin
toEffectful ::
forall (es :: Effects) (es' :: [EffectfulEffect]) a.
(Bluefin es ::> es') =>
(forall e. Effectful es' e -> Eff (e :& es) a) ->
-- | ͘
EffectfulEff es' a
toEffectful = unsafeToEffectful
fromEffectful ::
(e :> es) =>
(Proxy es -> EffectfulEff (Bluefin es : es') r) ->
Effectful es' e ->
-- | ͘
Eff es r
fromEffectful m (MkEffectful env) =
UnsafeMkEff (Effectful.unEff (unsafeInterpretBluefin (m Proxy)) env)
-- * Example code
example ::
( St.State Int Effectful.:> es,
Er.Error String Effectful.:> es,
Bluefin bes Effectful.:> es,
e :> bes
( St.State Int ::> es',
Er.Error String ::> es',
Bluefin es ::> es',
e :> es
) =>
State Int e ->
Proxy bes ->
Effectful.Eff es Int
Proxy es ->
-- | ͘
EffectfulEff es' Int
example bst (_ :: Proxy bes) = do
r <- St.get
St.put (r + 1 :: Int)
@ -116,14 +138,15 @@ example bst (_ :: Proxy bes) = do
St.get
bfExample ::
forall e es e1 effes.
forall e es e1 es'.
( e :> es,
e1 :> es,
St.State Int Effectful.:> effes,
Er.Error String Effectful.:> effes
St.State Int ::> es',
Er.Error String ::> es'
) =>
State Int e1 ->
Effectful effes e ->
Effectful es' e ->
-- | ͘
Eff es Int
bfExample s e = do
r <- fromEffectful (\_ -> example s (Proxy @es)) e
@ -146,3 +169,16 @@ runExample i =
-- Right 10
-- > runExample 10
-- Left "foo"
-- * Unsafe internals
voidBluefin :: Bluefin es m a -> r
voidBluefin = \case {}
unsafeInterpretBluefin ::
EffectfulEff (Bluefin es : es') a -> EffectfulEff es' a
unsafeInterpretBluefin = Effectful.interpret (\_ -> voidBluefin)
unsafeToEffectful :: (Effectful es e -> Eff es' a) -> EffectfulEff es a
unsafeToEffectful m =
Effectful.unsafeEff (\env' -> unsafeUnEff (m (MkEffectful env')))