Writing complex effects #88
-
|
I asked this on discourse about theseus, but I then started wondering, is it possible with bluefin to write an interpreter for equivalence of the following effect: data Fork :: Effect where
AsyncWithUnmask :: ((forall a. m a -> m a) -> m r) -> Fork m (Async r)that just wraps asyncWithUnmask from the async library? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 12 replies
-
|
Yes, the short answer is that you can do it as below. The longer answer is that this is a bit delicate because {-# LANGUAGE GHC2021 #-}
import Bluefin.Compound (mapHandle, useImplIn)
import Bluefin.Eff (Eff, (:>), (:&))
import Bluefin.IO (IOE, effIO, withEffToIO_)
import Control.Concurrent.Async qualified as Async
-- Making the new effect "Fork" as described in
-- https://hackage.haskell.org/package/bluefin/docs/Bluefin-Compound.html
newtype Fork e = MkFork (IOE e)
withFork ::
e1 :> es =>
IOE e1 ->
(forall e. Fork e -> Eff (e :& es) r) ->
Eff es r
withFork io k = useImplIn k (MkFork (mapHandle io))
asyncWithUnmask ::
e1 :> es =>
Fork e1 ->
((forall b. Eff es b -> Eff es b) -> Eff es r) ->
Eff es (Async.Async r)
asyncWithUnmask (MkFork io) m =
withEffToIO_ io $ \runInIO ->
Async.asyncWithUnmask (\f -> runInIO (m (effIO io . f . runInIO))) |
Beta Was this translation helpful? Give feedback.
OK, so how about the below?
Yes, the newtype wrapping helps (see below), although it is a bit of a pain to have to do that. There are various ways to make that syntactically more lightweight, but I hope this at least shows that it's possible and the resulting API is convenient, even if the plumbing is messy.
Interesting! I will have to investigate further to understand why it's possible in effectful (unless it's easy for you to summarize the reason for me).
But doesn't effectful have a problem with that feature? For example, I think this causes undefi…