2017-07-10 4 views
2

Ich bin neu bei Haskell, und ich bin mir nicht ganz sicher, wie die gleichzeitige I/O funktioniert. Ich untersuche, was mit den JACK-Audio-Bindungen erreicht werden kann. Grundsätzlich ist der folgende Code ist (fast) funktional, aber ich muss die Eingabetaste drücken zweimal jedesmal, wenn ich einen Wert eingeben:Haskell - Concurrent I/O Routing

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 

das Problem zu klären:

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" 

Ich bin nicht sicher, aber es scheint, dass der IO-Stream durch Threads durchlaufen wird. Gibt es eine Möglichkeit, das Programm dazu zu bringen, jede Eingabezeile anstelle jeder anderen Zeile zu lesen?

+1

Ich kann Ihr Problem nicht reproduzieren. Ziehen Sie in Betracht, einen MCVE zu erstellen, dies würde Importe einschließen, "runAudioStuff" ausschließen und das Testen des Beispiels einschließen, um sicherzustellen, dass es sich weiterhin falsch verhält. Meine Version verhält sich gut - wenn Ihre Version dies nicht tut, vermute ich, dass es sich um ein Problem mit Ihrem Terminal und nicht um ein Haskell-Problem handelt. –

Antwort

0

Implementierung ist immer wichtig. Es stellt sich heraus, dass runJackwaitForBreak in Sound.JACK genannt, was die Definition hat:

waitForBreak :: IO() 
waitForBreak = 
    let go = getLine >> go 
    in go 

Mit collectInput an seiner Stelle das Problem gelöst.