2012-01-23 24 views
5

non capisco perché questo codice esegue il ciclo solo una volta e poi esce? in Ghci posso rispondere solo al primo ciclo quindi sembra che la variabile cont sia impostata su false e non ho il prompt per rispondere.Ciclo con statoT: perché questo ciclo non fa il ciclo

Il risultato è:

*Main> testLoop1 td10 
test 
Do you want to continue? (y/N) 
y 
we continue 
test 
Do you want to continue? (y/N) 
We stop 

codice:

type TDeckSTIO = StateT TableDecks IO 

continue = do 
putStrLn "Do you want to continue? (y/N)" 
c <- getChar 
return $ c == 'y' 


loop1 :: TDeckSTIO() 
loop1 = do 
    liftIO $ putStrLn "test" 
    cont<- liftIO continue 
    if cont 
    then do 
     liftIO $ putStrLn "we continue" 
     liftIO $ testLoop1 td 

    else liftIO $ putStrLn "We stop" 

testLoop1 td = runStateT (loop1) td >> return() 

risposta

15

Il problema è che quando si digita y e premere invio, che in realtà è la digitazione due caratteri: 'y' stessa, e il carattere di nuova riga che viene inviato premendo il tasto Invio. La prima volta, il ciclo vede il 'y', ma la volta successiva, vede il '\n', e dal '\n' non è 'y', esce.

È possibile farlo hSetBuffering stdin NoBuffering prima di inserire il ciclo (avrete bisogno di importare System.IO), che vi permetterà di elaborare i caratteri senza attendere un ritorno a capo, o specificamente elaborare linee alla volta:

continue = do 
    putStrLn "Do you want to continue? (y/N)" 
    s <- getLine 
    return $ s == "y" 

A proposito, invece di scrivere liftIO $ testLoop1 td, puoi semplicemente rimanere nella stessa monade di stato: puoi sostituirlo con loop1 e funzionerà esattamente allo stesso modo.

Inoltre, testLoop1 è meglio scritto come:

testLoop1 = evalStateT loop1 

evalStateT è come runStateT, ma non include lo stato finale, quindi non c'è bisogno di scartare in modo esplicito il valore con >> return().

+0

Grazie esattamente quello che volevo e altro ancora. Ero sul percorso di ricerca quando ho appena cambiato il codice e aggiunto una stampa che mostra il '\ n'. Grazie per il suggerimento su liftIO $ testLoop1 td -> loop1. Questo è stato uno dei miei test precedenti e mi chiedevo quale di quei due codici sostituire. E buon punto con EvalState. Questa è stata la mia prima incursione con statetransformer e IO. –

Problemi correlati