Skip to content

Instantly share code, notes, and snippets.

@Lysxia
Created May 6, 2024 21:26
Show Gist options
  • Save Lysxia/c8ddafa285bf47ed8dd062c6302ded9d to your computer and use it in GitHub Desktop.
Save Lysxia/c8ddafa285bf47ed8dd062c6302ded9d to your computer and use it in GitHub Desktop.
{-# LANGUAGE
RankNTypes,
TypeOperators #-}
-- | User-defined handlers.
module Bluefin.Handlers
( Sig
, Handler
, with
, call
) where
import Data.Kind (Type)
import Bluefin.Internal (Eff, mergeEff, useImpl, type (:&), type (:>))
-- | Effect signatures as records of functions parameterized by the monad.
--
-- Example:
--
-- @
-- type State :: Type -> Sig
-- data State s m = MkState
-- { getF :: m s
-- , putF :: s -> m ()
-- }
-- @
type Sig = (Type -> Type) -> Type
type HandlerBody f s = f (Eff s)
newtype Handler f s = UnsafeMkHandler (HandlerBody f s)
-- ^ Internally, the scope @s@ is just the scope in which the handler
-- was defined.
-- | Handle an effect with signature @f@.
with ::
HandlerBody f s ->
(forall s0. Handler f s0 -> Eff (s0 :& s) a) ->
Eff s a
with handler action = mergeEff (action (UnsafeMkHandler handler))
-- | Example
--
-- @
-- get :: z0 :> z => Handler (State s) z0 -> Eff z s
-- get h = call h (\\r -> r.getF)
--
-- put :: z0 :> z => Handler (State s) z0 -> s -> Eff z ()
-- put h s = call h (\\r -> r.putF s)
-- @
call :: s0 :> s => Handler f s0 -> (forall m. f m -> m a) -> Eff s a
call (UnsafeMkHandler handler) op = useImpl (op handler)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment