Alexey Orlov
Alexey Orlov

Reputation: 2804

Haskell: looping over user input gracefully

This is an example from Learn You a Haskell:

main = do
    putStrLn "hello, what's your name?"
    name <- getLine
    putStrLn ("Hey, " ++ name ++ ", you rock!")

The same redone without do for clarity:

main =
    putStrLn "hello, what's your name?" >>
    getLine >>= \name ->
    putStrLn $ "Hey, " ++ name ++ ", you rock!"

How am I supposed to loop it cleanly (until "q"), the Haskell way (use of do discouraged)?

I borrowed this from Haskell - loop over user input

main = mapM_ process . takeWhile (/= "q") . lines =<< getLine
    where process line = do
                            putStrLn line

for starters, but it won't loop.

Upvotes: 0

Views: 828

Answers (2)

Redu
Redu

Reputation: 26161

May be you can also use laziness on IO type by adapting the System.IO.Lazy package. It basically includes only run :: T a -> IO a and interleave :: IO a -> T a functions to convert IO actions into lazy ones back and forth.

import qualified System.IO.Lazy as LIO

getLineUntil :: String -> IO [String]
getLineUntil s = LIO.run ((sequence . repeat $ LIO.interleave getLine) >>= return . takeWhile (/=s))

printData :: IO [String] -> IO ()
printData d = d >>= print . sum . map (read :: String -> Int)

*Main> printData $ getLineUntil "q"
1
2
3
4
5
6
7
8
9
q
45

In the above code we construct an infinite list of lazy getLines by repeat $ LIO.interleave getLine of type [T String] and by sequence we turn it into T [String] type and proceed reading up until "q" is received. The printData utility function is summing up and printing the entered integers.

Upvotes: 0

keep_learning
keep_learning

Reputation: 1077

You can call main again and check if your string is "q" or not.

import Control.Monad

main :: IO ()
main =
    putStrLn "hello, what's your name?" >>
    getLine >>= \name ->
                  when (name /= "q") $ (putStrLn $ "Hey, " ++ name ++ ", you rock!") >> main

λ> main
hello, what's your name?
Mukesh Tiwari
Hey, Mukesh Tiwari, you rock!
hello, what's your name?
Alexey Orlov
Hey, Alexey Orlov, you rock!
hello, what's your name?
q
λ> 

Upvotes: 1

Related Questions