Implementing Event Streams in Haskell using MVars
concurrency, haskell, io-monad, javascript, monads
Solution
When you run a Haskell program, it exits as soon as the main thread exits. You have a bit of a race condition: `getEvent`'s child threads are trying to get as much work done before the process exits.
One simple fix is to add an import line of `import Control.Monad (forever)` and then, at the end of `main`, run:
forever $ threadDelay maxBound
Which will cause the main thread to sleep forever. Better approaches depend on the purpose of your actual application.
Problem
I want to port the following JavaScript code to Haskell: http://jsfiddle.net/mz68R/ This is what I tried: ``` import Control.Concurrent import Data.IORef type EventStream a = IORef [MVar a] newEventStream :: IO (EventStream a) newEventStream = newIORef [] setEvent :: EventStream a -> a -> IO () setEvent stream event = readIORef stream >>= mapM_ (`putMVar` event) getEvent :: EventStream a -> (a -> IO b) -> IO ThreadId getEvent stream listener = do event <- newEmptyMVar modifyIORef stream (++ [event]) forkIO $ loop (takeMVar event >>= listener) loop :: Monad m => m a -> m () loop a = a >> loop a main = do fib <- newEventStream getEvent fib $ \(a, b) -> do print (a, b) setEvent fib (b, a + b) setEvent fib (0,1) ``` It partly works as expected: it doesn't produce an infinite list of Fibonacci numbers. It prints out varying numbers of Fibonacci numbers: ``` aaditmshah@home:~$ runhaskell EventStream.hs (0,1) (1,1) aaditmshah@home:~$ runhaskell EventStream.hs (0,1) (1,1) (1,2) (2,3) (3,5) aaditmshah@home:~$ runhaskell EventStream.hs (0,1) (1,1) (1,2) (2,3) (3,5) (5,8) (8,13) (13,21) (21,34) (34,55) (55,89) (89,144) (144,233) (233,377) (377,610) (610,987) (987,1597) (1597,2584) (2584,4181) (4181,6765) (6765,10946) ``` I believe that the problem is due to concurrency in the `getEvent` function but I can't put my finger on it. How do I refactor my code to alleviate this problem?