Reputation: 83
I've been trying to write a function that prints out a string letter by letter, without quotes, and pauses for a little in between each letter. For example, if you give it "hello", it'll print h, then wait, the e, then wait, then l, then wait, then l, then wait, the o. But when i try to use threadDelay
, it pauses in the main thread. So it'll pause, then print everything all at once. I tried to fork a new thread in the prints
function, but it doesn't work. Help!
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"
Upvotes: 2
Views: 122
Reputation: 29120
Your code has a few problems.
Firstly, threadDelay
takes an argument in microseconds, so the pause you are adding is too small to notice. Try 1000000
.
Secondly, unless you turn off buffering on stdout
, the IO library will buffer up your output so you won't see it with the expected delays. You can control this with System.IO
:
import System.IO ( stdout, hSetBuffering, BufferMode(..) )
and then call hSetBuffering
from main
:
hSetBuffering stdout NoBuffering
Finally, forking off a thread is actually a step backwards, because the program doesn't wait for the forked threads to finish, so just remove that. If you really want it to be in the background, you'll need to use an MVar
or similar to wait for it to finish if the program will otherwise naturally exit first.
Upvotes: 4