I’ve always been a coroutines fan, implementing them even in C J. In Haskell, coroutines can be started with forkIO call, and to pass control and data you can use MVar/TVar/Chan or semaphores. I filled a small library for arranging these tasks, which can be downloaded as Process library at http://freearc.narod.ru. For example, one process can perform:

            sendP pipe data

receive_backP pipe     -- wait for acknowledgment

and another process can do:

            data <- receiveP pipe

            process received data

send_backP pipe ()   -- send acknowledgment