Reputation: 43360
I need to run multiple concurrent processes in a context of the same monad, say, Connection
. I expected something like the following would work:
main = runConnection connectionSettings $ do
forkIO action1
forkIO action2
action3
but forkIO
required to be run in an IO
context and actions to be in IO
too.
Assuming those actions have a type :: Connection ()
, what needs to be done to run them concurrently (which instances to implement and etc)?
Currently I'm working around this as follows, but evidently this ain't right:
main = do
forkIO $ runConnection connectionSettings action1
forkIO $ runConnection connectionSettings action2
runConnection connectionSettings action3
Upvotes: 4
Views: 387
Reputation: 43360
I've found a beautiful "monad-parallel" library intended for very similar purposes, and an even more powerful fork of it - "classy-parallel".
For a monad to be usable in a parallelizable manner it needs to have an instance of a Parallel
typeclass. And the "classy-parallel" library already provides instances for the most important types for such purposes: ResourceT IO
and ReaderT
.
Assuming the presence of appropriate instances the code in question can be transformed to following:
import qualified Control.Monad.Parallel as Parallel
main = runConnection connectionSettings $
Parallel.sequence [action1, action2, action3]
For simply forking in ResourceT
the resourceForkIO
can be useful. There's also a "monad-fork" library which provides a neat and simple generalization over forking on top of forkIO
and resourceForkIO
.
Upvotes: 3