2012-02-09 13 views
8

Sto provando a scrivere un clone di urlview in Haskell. Il programma legge un messaggio (inviato tramite STDIN), estrae tutti gli URL e chiede all'utente di selezionarne uno.Come posso resettare lo stdin in Haskell?

Dopo aver letto il messaggio, STDIN raggiunge ovviamente EOF. In Python, ho resettato STDIN come questo

message = sys.stdin.read() 
sys.stdin = open('/dev/tty') 
selected_index = raw_input('Which URL to open? ') 

Come potrei ottenere lo stesso in Haskell?

risposta

7

Per quanto ne so non c'è modo di "riassegnare" lo stdin integrato in Haskell, ma in alternativa è possibile aprire un nuovo handle su /dev/tty. Una traduzione diretta del codice Python sarebbe qualcosa di simile

import System.IO 

main = do 
    message <- getContents 
    tty <- openFile "/dev/tty" ReadMode 
    putStr "Which URL to open? " 
    url <- hGetLine tty 
    ... 
8

Non è possibile cambiare la maniglia stdin in Haskell. In Python, le variabili sys.stdin soli punti a una maniglia, in modo che quando si sostituiscono con un nuovo handle di file, il vecchio stdinmaniglia rimane, ma il sys.stdinvariabile ora contiene l'handle di file.

Poiché l'handle System.IO.stdin è immutabile in Haskell (come lo sono molte altre variabili, o dovrei dire valori), non è possibile fare la stessa cosa in Haskell.

Quello che puoi fare è aprire il file /dev/tty con una nuova maniglia e usarlo per leggere dal terminale. È possibile utilizzare tutte le stesse operazioni su qualsiasi handle possibile su stdin. È sufficiente importare System.IO e ogni volta che si usa il foo ... per ottenere qualche input, utilizzare invece hFoo handle .... Per esempio, per leggere una riga dal terminale, di questo codice:

import System.IO 

-- ... 
newstdin <- openFile "/dev/tty" ReadMode 
-- Instead of normal getLine; just prepend "h" and pass the handle 
line <- hGetLine newstdin 

Non dimenticare di chiudere il nuovo manico con una chiamata a hClose!