-2
\$\begingroup\$

I want to capture some state in a Haskell function. For instance, I have many thread trying to print on the console and I want the to play nice with each other. So I want to have some XX to make the police among the threads and I want that to be hidden as most as possible to my client.

I can think of a few alternatives, but I am not sure what is the most idiomatic in Haskell:

  • Write a logger running on his independent thread, as in the parallel and concurrent Haskell book.

  • Write a function like so:

    getPutStrLn' :: IO (String -> IO ())
    getPutStrLn' = do
       sync <- newMVar ()
       return (\s -> do _ <- takeMVar sync
                        putStrLn s
                        putMVar sync ())
    
  • Separate concerns and put the said state somewhere else, calling getPutStrLn as part of a pipeline of effectual streams but not from within the threads.

\$\endgroup\$

migrated from stackoverflow.com Jun 11 '16 at 15:46

This question came from our site for professional and enthusiast programmers.

  • 1
    \$\begingroup\$ Sounds like a textbook example of message passing: a bunch of threads writing console messages to a TQueue, and one thread reading from it in a loop and printing each message \$\endgroup\$ – Benjamin Hodgson May 28 '16 at 12:33
2
\$\begingroup\$

What you have will work just fine:

import Control.Concurrent
import Control.Concurrent.MVar
import Control.Monad

getPutStrLn' :: IO (String -> IO ())
getPutStrLn' = do
   sync <- newMVar ()
   return (\s -> do _ <- takeMVar sync
                    putStrLn s
                    putMVar sync ())

type Logger = String -> IO ()

second = 1000000

child1 :: Logger -> IO ()
child1 log = do
  forever $ do log "I am child 1"
               threadDelay (1*second)

child2 log = do
  forever $ do log "I am child 2"
               threadDelay (2*second)

main = do
  log <- getPutStrLn'
  forkIO $ child1 log
  forkIO $ child2 log
  threadDelay (10*second)

You are encapsulating the state in the log computation - that's the perfect place for it.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.