Polysemy: Tactics binding deprecated workaroundGautier DI FOLCO January 29, 2023 [Haskell] #haskell #polysemy #design #effects systems
In a previous log, we ended with a solution for
Resource which wasn't
The solution is to use the soo-deperecated
Let's start again with our simpler effect
data BindE (m :: Type -> Type) a where BindE :: m a -> (a -> m b) -> BindE m b makeSem ''BindE
We can express an impure (
= interpretH $ \case BindE f g -> do ma <- runT f mf <- bindT g withLowerToIO $ \lower _ -> do let toIO :: Sem (BindE ': r) x -> IO x toIO = lower . raise . interpretBindTacticLowering toIO ma >>= toIO . mf interpretBindTacticLowering
withLowerToIO provides two functions (one to locally interpret a
Sem r a to
IO a and a finalizer) and expect a
IO a, it's defined as:
withLowerToIO :: Member (Embed IO) r => ((forall x. Sem r x -> IO x) -> IO () -> IO a) -> Sem r a
Under the hood, a thread is created (the program should be compiled with
-thread) to run the effect stack until
IO, 'blocking' thread.
The finalizer does not need to be called, but it indicate the end of the new thread.
Let's see how it goes for
data Resource m a where Bracket :: m a -> (a -> m c) -> (a -> m b) -> Resource m b
We are now able to use
= interpretH $ \case Bracket alloc dealloc use -> do alloc' <- runS alloc dealloc' <- bindS dealloc use' <- bindS use withLowerToIO $ \lower finish -> do let runHoE :: Sem (Resource ': r) x -> IO x runHoE = lower . raise . resourceToIO Expection.bracket (runHoE alloc') (\x -> runHoE (use' x) >> finish) (runHoE . dealloc') resourceToIO
See the full the code here and here.