为了练习并发编程,我编写了以下(次优)程序,该程序反复计算比用户输入的值大的第一个素数:

import Control.Concurrent
import Control.Concurrent.Chan
import Control.Monad (forever)
primeAtLeast n = -- Some pure code that looks up the first prime at least as big as n

outputPrimeAtLeast n = putStrLn $ show $ (n, primeAtLeast n)

main = do
    chan <- newChan
    worker <- forkIO $ forever $ readChan chan >>= outputPrimeAtLeast
    forever $ (readLn :: (IO Int)) >>= (writeChan chan)
    killThread worker


我想要在后台进行实际计算并在完成后立即输出(n, primeAtLeast n)的工作线程。

现在的操作:输入数字n后,它将立即输出(n,,将控件返回到主线程,在后台计算primeAtLeast n,并在输出后立即输出后半部分primeAtLeast n)。完成。

那么putStrLn不是原子的吗?还是问题出在哪里?

最佳答案

试试这个:

outputPrimeAtLeast n = let p = primeAtLeast n in p `seq` putStrLn $ show (n, p)


以上在putStrLn运行之前强制计算素数。

此外,您可以使用print代替putStrLn . show

outputPrimeAtLeast n = let p = primeAtLeast n in p `seq` print (n, p)


另外,您可以使用putStrLn函数在开始打印任何内容之前强制每个字符。

strictPutStrLn :: Show a => a -> IO ()
strictPutStrLn x = let str = show x in str `listSeq` putStrLn str

listSeq :: [a] -> b -> b
listSeq []     w = w
listSeq (x:xs) w = x `seq` listSeq xs w

09-30 12:06