One example which should be pretty easy to implement would be a #lang where some of the effects are ambient (like exceptions and spark-level parallelism in Haskell) rather than tracked (like ExceptT and forkIO). It should be possible to take any monad and to make its effect ambient by rewriting #%app to >>=, rewriting (-> Integer Integer) to (-> Integer (MyMonad Integer), etc.
(-> Integer (State S A)) would not need to be rewritten to (-> Integer (StateT S MyMonadT A)), just to (-> Integer (MyMonad (State S A))). That MyMonad represents the fact that ambient effects can occur while calculating which(State S A) action to return. When executing that action, MyAction effects can also be performed... Because when Monad is defined inside that #lang, the user writes that the type of >>= is (-> A (State S B)), but that actually means (-> A (MyMonad (State S B)))! So each time the (strict!) implementation of runState calls that continuation in order to get the next State S B action on which to recur, the MyAction effects occur, interleaved with the state effects as desired.
Which effect should the example use? While the effects which would make the most sense to use in the example are exceptions and mutable state, neither of those actually work because
The set of exception types is usually open while ExceptT tracks one specific error type.
Each function usually defines its own local mutable variables, while StateT tracks one single global state. The ST monad would be more appropriate here, but Klister's runtime doesn't support that yet.
One example which should be pretty easy to implement would be a
#lang
where some of the effects are ambient (like exceptions and spark-level parallelism in Haskell) rather than tracked (like ExceptT and forkIO). It should be possible to take any monad and to make its effect ambient by rewriting#%app
to>>=
, rewriting(-> Integer Integer)
to(-> Integer (MyMonad Integer)
, etc.(-> Integer (State S A))
would not need to be rewritten to(-> Integer (StateT S MyMonadT A))
, just to(-> Integer (MyMonad (State S A)))
. ThatMyMonad
represents the fact that ambient effects can occur while calculating which(State S A)
action to return. When executing that action,MyAction
effects can also be performed... Because whenMonad
is defined inside that#lang
, the user writes that the type of>>=
is(-> A (State S B))
, but that actually means(-> A (MyMonad (State S B)))
! So each time the (strict!) implementation ofrunState
calls that continuation in order to get the nextState S B
action on which to recur, theMyAction
effects occur, interleaved with the state effects as desired.