I am new to Haskell, and I'm not exactly sure how the concurrent I/O works. I'm exploring what can be accomplished with the JACK audio bindings. Basically, the following code is (almost) functional, but I need to press enter twice every time I input a value:
collectInput :: IORef Double -> IO ()
collectInput freq = forever $ do
putStr ">> "
hFlush stdout
f <- getLine
case readMaybe f of
Just x -> do
putStrLn $ show x
writeIORef freq x
Nothing -> do
putStrLn "Nada"
main :: IO ()
main = do
freq <- newIORef 440
_ <- forkIO $ runJackStuff freq
collectInput freq
To clarify the problem:
Input | Result | Output
----------------------------------------
330 | Frequency changes | ">> 330.0"
440 | Nothing happens | ""
220.0 | Frequency changes | ">> 220.0"
550.0 | Nothing happens | ""
bleh | Outputs "Nada" | ">> Nada"
| Nothing Happens | ""
foo | Outputs "Nada" | ">> Nada"
I'm not sure, but it would seem that the IO stream is cycled through threads. Is there a way to make the program read every line of input, instead of every other line?
Implementation always matters. It turns out that runJack
called waitForBreak
in Sound.JACK, which has the definition:
waitForBreak :: IO ()
waitForBreak =
let go = getLine >> go
in go
Using collectInput
in its place solved the problem.