2

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?

4

1 回答 1

0

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.

于 2017-07-10T06:09:09.200 回答