Nikita Volkov
Nikita Volkov

Reputation: 43360

Multithreading in a monad

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

Answers (1)

Nikita Volkov
Nikita Volkov

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

Related Questions