Ответ 1
Это хороший вопрос. Используйте переменную синхронизации для обеспечения атомарного доступа к ресурсу. Простым способом является MVar:
main = do
lock <- newMVar ()
forkIO $ ... lock
forkIO $ ... lock
Теперь, чтобы выполнить IO без чередования, каждый поток принимает блокировку:
thread1 lock = do
withMVar lock $ \_ -> putStrLn "foo"
thread2 lock = do
withMVar lock $ \_ -> putStrLn "bar"
Альтернативный дизайн состоит в том, чтобы иметь выделенный рабочий поток, который выполняет все putStrLns, и вы отправляете сообщения для печати через Chan.