-
I have the following: data MoverAllocator :: Effect where
WithMover :: MoverToken -> Eff (Mover : es) r -> MoverAllocator (Eff es) r
data Mover :: Effect where
WithMoverAt :: Point V2 Int -> m a -> Mover m a When I go to implement this, I have: runMoverAllocator ::
(Concurrent :> es, IOE :> es) =>
MoverFleet -> Eff (MoverAllocator : es) a -> Eff es a
runMoverAllocator moverFleet = reinterpret runMoverRouting \localEnv -> \case
WithMover moverToken k ->
localSeqUnlift localEnv \unlift -> do
localSeqLend @IOE localEnv \runIOE -> do
unlift $
runIOE $
runConcurrent $
interpret
(withMoverHandler (index s moverId))
(inject k)
where
withMoverHandler ::
(SharedSuffix es handlerEs, IOE :> es, Concurrent :> es, MoverRouting :> es) =>
MoverState ->
LocalEnv localEs handlerEs ->
Mover (Eff localEs) a ->
Eff es a
withMoverHandler s localEnv = \case
WithMoverAt p k ->
localSeqUnlift localEnv \unlift -> do
routeMover s.moverId p do
unlift k Note that in data MoverRouting :: Effect where
RouteMover ::
{ moverId :: MoverId
, target :: Point V2 Int
, m :: Eff es a
} ->
MoverRouting (Eff es) a This effect is available in WithMover moverToken k ->
localSeqUnlift localEnv \unlift -> do
localSeqLend @IOE localEnv \runIOE -> do
localSeqLend @MoverRouting localEnv \runMoverRouting -> do
-- Block until this acqusition is complete.
moverId <- atomically moverToken.acquire
s <- get @(Movers MoverState)
unlift $
runIOE $
runMoverRouting $
runConcurrent $
interpret
(withMoverHandler (index s moverId))
(inject k) which doesn't type check:
I understand this is a very convoluted set up and I have ways to change, but it does nonetheless seem to highlight something that's currently impossible. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
My fix for this is currently to define: extendLocalEnv
:: (e :> es, SharedSuffix es handlerEs)
=> LocalEnv localEs handlerEs
-> Eff es (LocalEnv (e : localEs) handlerEs)
extendLocalEnv (LocalEnv les) = unsafeEff $ \es -> LocalEnv <$> copyRef es les Then I can do: WithMover moverToken k -> do
localEnv <- extendLocalEnv @IOE localEnv
localEnv <- extendLocalEnv @MoverRouting localEnv
localSeqUnlift localEnv \unlift -> do
unlift $
runConcurrent $
interpret
(withMoverHandler (index s moverId))
(inject k) But I have no idea how safe that is! |
Beta Was this translation helpful? Give feedback.
-
Oh, I considered lending multiple effects when adding these functions, but didn't test it and so didn't realize that scoped runners are constrained to I guess I'll have to change this to accept a list of effects to borrow/lend, so you can say As for this particular instance, your data MoverToken
data Mover :: Effect where
WithMoverAt :: Int -> m a -> Mover m a
type instance DispatchOf Mover = Dynamic
data MoverRouting :: Effect where
RouteMover :: Int -> m a -> MoverRouting m a
type instance DispatchOf MoverRouting = Dynamic
runMoverRouting :: Eff (MoverRouting : es) a -> Eff es a
runMoverRouting = undefined
runMover :: {- ... => -} MoverToken -> Eff (Mover : es) a -> Eff es a
runMover token action = do
-- Block until this acqusition is complete.
-- moverId <- atomically moverToken.acquire
-- s <- get @(Movers MoverState)
reinterpretWith runMoverRouting action $ \env -> \case
WithMoverAt p k -> localSeqUnlift env $ \unlift ->
send $ RouteMover p (unlift k) And then you can use |
Beta Was this translation helpful? Give feedback.
-
Fixed by #234. |
Beta Was this translation helpful? Give feedback.
Fixed by #234.