2012-03-17 13 views
7

Jestem całkiem nowy dla Haskella, i chciałbym dalej czytać linie z konsoli do końca strumienia i wypisywać wszystko, co otrzymuję dużymi literami. Do tej pory mamCzytaj do końca strumienia w haskell

import Data.Char 

main = myLoop 

myLoop = do inp <- getLine 
      if (inp == "x") 
       then putStrLn "Bye!" 
       else do putStrLn(map toUpper inp) 
         myLoop 

Jednak nie wydaje się dowiedzieć się, jak uniknąć stanu if (inp == "x") i zastąpić go z końcem stanu strumienia.

Krótko mówiąc, szukam odpowiednika Haskell do while (cin >> line) w C++

+0

Powinieneś wybrać odpowiedź od Dave4420 - oznacza to, że osoby, które mają problem, opisują, które z rozwiązań faktycznie na nie odpowiedziały. – Titou

Odpowiedz

8

To wykracza poza to, czego naprawdę prośbą o, ale używam tego wzorca dużo: interact:

myFun :: String -> String 
myFun = ... 

main = interact (unlines . myFun . lines) 

Twoja funkcja myFun będą wykonywane przed każdym wierszu standardowego wejścia, a wynik wysłany na standardowe wyjście.

+0

Przypuszczam, że jest to ciekawość ghci, ale 'main = interakcję (unlines. Map (map toupper). Lines) >> putStrLn" bye "' nie działa wewnątrz ghci - to jest jak "oddziałaj z" Uperupem "- ale robi to, czego chce Kshitij Mehta, jeśli skompilujesz lub użyjesz runhaskell – applicative

+0

@aplikacyjny, co nie działa w tym przypadku? Jedyną dziwną rzeczą, którą napotkałem, jest to, że zamiast używać CTRL-D do sygnalizowania końca wejścia, musisz przerwać to za pomocą CTRL-C. To samo dotyczy interakcji "ghc -e" (bez linii, map do linii)) putStrLn \ "bye \" " –

+0

Wewnątrz ghci, pierwsza linia" pierwsza linia "wygląda następująco' fFiIrRsStT LLiInNeE' – applicative

15

Korzystanie isEOF z System.IO.

import System.IO (isEOF) 
import Data.Char 

main = myLoop 

myLoop = do done <- isEOF 
      if done 
       then putStrLn "Bye!" 
       else do inp <- getLine 
         putStrLn (map toUpper inp) 
         myLoop 
+0

Może to być nieco lepszy styl użycia 'until done $ do ...', ponieważ nie ma żadnego sensownego obliczenia w gałęzi 'done == True'. –

+0

Odpowiedzi na pytanie + daje rozwiązanie, które działa na naprawdę długich plikach – Titou

4

Można również polegać na leniwym IO.

import Data.Char 

main :: IO() 
main = do 
    inp <- getContents 
    let ls = lines inp 
     upcased = map (map toUpper) ls 
    mapM_ putStrLn upcased 
1

Inną opcją jest użycie when której dokumentację można znaleźć here:

import System.IO (isEOF) 
import Data.Char (toUpper) 
import Control.Monad (forever, when) 
import System.Exit (exitSuccess) 
main = myLoop 

myLoop = forever $ do 
       done <- isEOF 
       when done $ putStrLn "Bye!" >> exitSuccess 
       inp <- getLine 
       putStrLn (map toUpper inp) 
       myLoop 

przeciwnym razie odpowiedź jest identyczna the one by @dave4420.

+0

Uwielbiam twoją odpowiedź, stary. – Ch3shire