我一直在尝试编写一个函数,用字母逐字打印一个字符串,不带引号,并在每个字母之间暂停一点。例如,如果你给它“hello”,它将打印h,然后等待,e,然后等待,然后l,然后等待,然后l,然后等待,o。但是当我尝试使用threadDelay
时,它会在主线程中暂停。所以它会暂停,然后一次打印所有内容。我试图在prints
函数中分叉一个新线程,但它不起作用。救命!
import Control.Concurrent as C
clean :: String -> String
clean s@[c] = s
clean ('"':s)
| last s == '"' = init s
| otherwise = s
clean ('\'':s)
| last s == '\'' = init s
| otherwise = s
clean s = s
prints :: String -> IO()
prints [] = putStrLn " "
prints (x:xs) = do
C.forkIO $ do
putStr $ clean (show x)
C.threadDelay $ 10000
prints xs
main :: IO()
main = do
prints "hello"
答案 0 :(得分:4)
您的代码存在一些问题。
首先,threadDelay
在微秒中接受一个参数,因此您添加的暂停太小而无法注意到。试试1000000
。
其次,除非您关闭stdout
上的缓冲,否则IO库会缓冲您的输出,因此您将看不到预期的延迟。您可以使用System.IO
控制此项:
import System.IO ( stdout, hSetBuffering, BufferMode(..) )
然后从hSetBuffering
致电main
:
hSetBuffering stdout NoBuffering
最后,分离一个线程实际上是一个倒退,因为程序不会等待分叉的线程完成,所以只需删除它。如果你真的希望它在后台,你将需要使用MVar
或类似的等待它完成,否则程序将自然地首先退出。