2012-02-09 18 views
8

Próbuję napisać klon urlview w Haskell. Program odczytuje komunikat (przesyłany przez STDIN), wyodrębnia wszystkie adresy URL i prosi użytkownika o wybranie jednego z nich.Jak zresetować stdin w Haskell?

Po przeczytaniu komunikatu STDIN ewidentnie osiąga EOF. W Pythonie zresetować STDIN jak ten

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

Jak chciałbym osiągnąć to samo w Haskell?

Odpowiedz

7

O ile mi wiadomo, nie ma sposobu, aby "ponownie przypisać" wbudowany stdin w Haskell, ale można inaczej otworzyć nowy uchwyt do /dev/tty. Bezpośrednie tłumaczenie kodu Pythona byłoby coś

import System.IO 

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

Nie można zmienić uchwyt stdin w Haskell. W Pythonie, że sys.stdin zmiennej tylko punkty do uchwytu, dzięki czemu podczas zastąpić go nowym uchwytu pliku, stary stdinuchwyt nadal pozostaje, ale sys.stdinzmienna teraz zawiera uchwyt pliku.

Ponieważ uchwyt System.IO.stdin jest niezmienny w Haskell (ponieważ jest tak wiele innych zmiennych, lub powinienem powiedzieć wartości), nie można zrobić tego samego w Haskell.

Możesz otworzyć plik /dev/tty za pomocą nowej klamki i użyć tego uchwytu do odczytania z terminala. Możesz użyć wszystkich tych samych operacji na dowolnym uchwycie, jak to możliwe na stdin. Po prostu zaimportuj System.IO, a za każdym razem, gdy w przeciwnym razie użyjesz foo ..., aby uzyskać pewne dane wejściowe, zamiast tego użyj hFoo handle .... Na przykład, aby przeczytać linię od terminalu, użyj tego kodu:

import System.IO 

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

nie zapomnij zamknąć nowy uchwyt z wezwaniem do hClose!