I have some pipes-concurrency code that looks like this:
-- this won't compile but will give you the gist of what's happening
pipeline :: MonadIO m => Consumer a m ()
main = do
(output, input) <- spawn Unbounded
async $ do runEffect $ fromInput input >-> pipeline
performGC
-- skipped the `output` pipeline code.
Question 1: This obviously won't compile since runEffect will return MonadIO m => m () and async requires IO a. Is there a way to do this? Or am I stuck forcing my pipeline to contain effects within the IO monad?
Question 2: does it even make sense to embed an async within a Monad implementing MonadIO? Not sure if I'm articulating myself well here.
Thank you!
This obviously won't compile since
runEffectwill returnMonadIO m => m ()and async requiresIO a
That's not quite right. IO is an instance of MonadIO so your output of runEffect could be passed to async or e.g. a function taking MaybeT IO () (also a MonadIO instance).
I think what you're looking for is liftIO :: IO a -> m a, which will let you "lift" the specific IO (Async a) returned by async to a polymorphic MonadIO type as called for in your type signature.
...
liftIO $ async $ do runEffect $ fromInput input >-> pipeline
performGC
Haven't tried to compile this; you may need to lift other IO parts of your functions as well.
Question 2: does it even make sense to embed an async within a Monad implementing MonadIO? Not sure if I'm articulating myself well here.
Sure, if you want to do concurrency in some monad stack why not?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With