Skip to content

Commit

Permalink
Some docs
Browse files Browse the repository at this point in the history
  • Loading branch information
tomjaguarpaw committed Oct 30, 2024
1 parent 0831e46 commit 9db210f
Showing 1 changed file with 102 additions and 66 deletions.
168 changes: 102 additions & 66 deletions bluefin-internal/src/Bluefin/Internal/Effectful.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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

data Bluefin es m a
-- | Provide access to Effectful operations in Bluefin
newtype Effectful (es' :: [EffectfulEffect]) (e :: Effects)
= MkEffectful (Env es')

type instance DispatchOf (Bluefin es) = Dynamic
-- * Effectful effect

voidBluefin :: Bluefin es m a -> r
voidBluefin = \case {}
-- | Provide access to Bluefin operations in Effectful
data Bluefin es m a

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 synonyms

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 instance DispatchOf (Bluefin es) = Dynamic

toEffectful ::
forall es effes a.
(Bluefin es Effectful.:> effes) =>
(forall e. Effectful effes e -> Eff (e :& es) a) ->
Effectful.Eff effes a
toEffectful = unsafeToEffectful
type EffectfulEff = Effectful.Eff

unsafeInterpretBluefin ::
Effectful.Eff (Bluefin es : effes) a -> Effectful.Eff effes a
unsafeInterpretBluefin = Effectful.interpret (\_ -> voidBluefin)
type EffectfulEffect = Effectful.Effect

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)
type a ::> b = a Effectful.:> b

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) =>
Expand All @@ -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)
Expand All @@ -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
Expand All @@ -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')))

0 comments on commit 9db210f

Please sign in to comment.