I'm trying to learn Haskell to get used to functional programming languages. I've decided to try a few problems at interviewstreet to start out. I'm having trouble reading from stdin and doing io in general with haskell's lazy io.
Most of the problems have data coming from stdin in the following form:
n
data line 1
data line 2
data line 3
...
data line n
where n is the number of following lines coming from stdin and the next lines are the data.
How do I run my program on each of the n lines one at a time and return the solution to stdout?
I know the stdin input won't be very large but I'm asking about evaluating each line one at a time pretending the input is larger than what can fit in memory just to learn how to use haskell.
You can use interact, in conjunction with lines to process data from stdin one line at a time. Here's an example program that uses interact to access stdin, lines to split the data on each newline, a list comprehension to apply the function perLine to each line of the input, and unlines to put the output from perLine back together again.
main = interact processInput
processInput input = unlines [perLine line | line <- lines input]
perLine line = reverse line -- do whatever you want to 'line' here!
You don't need to worry about the size of the data you're getting over stdin; Haskell's laziness ensures that you only keep the parts you're actually working on in memory at any time.
EDIT: if you still want to work on only the first n lines, you can use the take function in the above example, like this:
processInput input = unlines [perLine line | line <- take 10 (lines input)]
This will terminate the program after the first ten lines have been read and processed.
You can also use a simple recursion:
getMultipleLines :: Int -> IO [String]
getMultipleLines n
| n <= 0 = return []
| otherwise = do
x <- getLine
xs <- getMultipleLines (n-1)
return (x:xs)
And then use it in your main:
main :: IO ()
main = do
line <- getLine
let numLines = read line :: Int
inputs <- getMultipleLines numLines
Related
My function works ok. But I want to use this function with a file's text. The text file has a word before an integer list. How can I do this?
This is the function:
broke :: Integer -> Integer
broke n = pollard 1 2 n 2 2
The contents of the file is:
Word (11,12)
I want to apply the function broke to the first number.
Well this might be kind of a cheat, but the contents of that file is a valid Haskell expression so you could use Read to do it:
import System.IO (readFile)
data Word = Word (Integer,Integer)
deriving (Read)
main = do
contents <- readFile "path/to/file" -- or wherever your file is
let Word (x,y) = read contents
print $ broke x
The reason this works is that deriving (Read) automatically writes a parser for you, so you get the function read :: String -> Word for free. So this technique is only going to work for files whose contents look like Haskell -- otherwise you will need to write your own parser.
I am writing a program in Haskell which repeatedly takes its most recent result and uses this to compute the next result. I want to be able to see the newest result in response to user input, so I tried something like this:
main = mainhelper 0
mainhelper count = do
count <- return (count + 1)
line <- getLine
if null line
then do mainhelper count
else do
putStrLn $ show count
return ()
I was hoping that getLine would return an empty line if the user hasn't entered anything, but this doesn't happen, instead the program does nothing until it receives user input. Is there a way around this?
One simple solution is to fork a thread for the complicated computation and communicate with the main UI thread via MVar. For example:
import Control.Exception
import Control.Monad
import Control.Concurrent
thinkReallyHard x = do
threadDelay 1000000 -- as a proxy for something that's actually difficult
evaluate (x+1)
main = do
v <- newMVar 0
forkIO (forever (modifyMVar_ v thinkReallyHard))
forever (getLine >> readMVar v >>= print)
You may wonder about the role of evaluate in thinkReallyHard. The subtlety there is that MVars are lazy -- they can contain thunks just as easily as computed values. In particular, this means it's easy to accidentally push all the pure computation from the forked thread into the thread that's reading and using the contents of the MVar. The call to evaluate simply forces the forked thread to finish the pure computation before writing to the MVar.
It does return an empty line if you hit enter without entering text -- you just immediately prompt for more input, so it might look like nothing is happening. But if you run the program, hit enter three times, then enter something non-empty, you'll see that the final count reflects the multiple entries.
Here's a modified version of your code that does the same thing, but is slightly more canonical:
main = mainhelper 0
mainhelper count = do
let count' = count + 1
line <- getLine
if null line
then mainhelper count'
else print count'
Rather than count <- return (count + 1), you can write let count' = count + 1 -- this is a pure binding, not something that needs to invoke the IO monad (as you're doing with <- and return). But I used count' instead of count because otherwise that will create a recursive binding. The '-suffixing is a standard idiom for a "modified version" of an identifier.
Next I switched putStrLn . show to print, which is part of the Prelude and does exactly that.
I got rid of the return () because print (and putStrLn) already have the type IO (). This allows you to elide the do statements, as there's now a single IO expression in each branch of the if.
It's not really clear what you're trying to do here that's different from what you are doing -- the code does (in imperative terms) increment a counter every time the user presses enter, and displays the state of the counter every time the user enters some non-empty text.
Here's another version that prints the counter every time, but only increments it when prompted, which may or may not be helpful to you:
main = mainhelper 0
mainhelper count = do
print count
line <- getLine
mainhelper (if null line then count else succ count)
I'm using succ, the successor function, instead of the explicit + 1, which is just a style preference.
I'm learning some Haskell and I came across this small program
reverseLines :: String -> String
reverseLines input =
unlines (map reverse (lines input))
main :: IO ()
main = interact reverseLines
This program will keep asking the user for more input and reverse the input and print it on the screen.
Most of this is straight forward but one thing I can't wrap my head around is why does this function keeps running and ask the user for more input whereas if I just replace the reverseLines function with a function the simply returns some string it will not happen.
This program will stop after one execution:
foo input = "Stops"
main :: IO ()
main = interact foo
Why?
If you look at the source of interact you see this:
interact f = do s <- getContents
putStr (f s)
see the getContents? This is where the magic starts - it will read everything till EOF
Now in Haskell this is lazy-IO which can be bad but here is almost magical - see the string is read lazily and passed to your reverseLines - this one of course will only generate output as soon as it saw \n characters (the lines) and so it seems your program is some kind of REPL.
In the second one you don't consume any of the lazy-string at all so it stops ASAP
As I wrote in the comments you can play with this by either passing content into the program using a file (or echo) and pipes on the terminal:
echo "Hello World\nBye Bye" | runhaskell LazyIO.hs
or using CTRL-D to pass in the EOF yourself.
To get a feeling for it I would play with the functions more - what happens if you use something that needs to see the complete input first (try reverse without the maps)? What happens with words instead of lines, ...?
Have fun!
I'm trying to read from standard input line by line, and process each line with the function of the type foo :: String -> Int. Is there any way to do that provided that we don't know the number of lines we want to read OR given that the number of lines is provided on the first line?
What I've tried
A lot of things that give meaningless errors, such as "parser error".
For example
main = do {
getLine <- getContents;
let result = show (foo getLine);
putStrLn (foo result);
}
Edit
Strange, but this does not print the length of a
main = do {
a <- getContents;
putStrLn (show (length a));
}
but, this does print 5.
main = do {
a <- getContents;
putStrLn (show 5);
}
The main example of doing that will look as this:
main = do
line <- getLine
yourfunction line
main
this will take lines forever and process them with your function, in case you want it to stop sometime, just check for a command for example:
main = do
line <- getLine
let res = yourfunction line
if res == "Exit" then IO () else main
You may use the function lines to convert the String into [String]. Afterwards map your foo over this list of lines.
Regarding the edit: Your program printing the length works for me. Try either inputting a file or - if entering input interactively - terminating it correctly (via Ctrl-d).
Sidenote: curly brackets and semicolons are rarely seen usually. But this is just style.
I have question related Haskell language.i need to store bunch of characters in 2D array.How can i store it??I have characters in 10 X 10 format in text file and i want to store it in 2D character array in haskell language.Please help me as soon as possible..thank you..
Here is the code which i tried and in this code i am trying to store value of x in the list named listofchar::
module TreasureFile where
import System.IO
main = do
hdl <- openFile "map.txt" ReadMode
readbychar hdl
readbychar hdl = do
t <- hIsEOF hdl
if t
then return()
else do
let listofchar=[]
x <- hGetChar hdl
if x =='\n'
then putChar '!'--return()
else listofchar x
readbychar hdl
Try this:
import System.IO
main = do
textContents <- readFile "map.txt"
let map = format textContents
print $ map
format text = lines text
Lets step through this program:
First, readFile reads us the file and binds the contents to textContents.
Next we format the contents by splitting the list every time we encounter a newline delimiter and then remove the eventually remaining empty strings.
Done! Now we can do whatever we want with our "map".
A small note on the side:
It will seem strange that our map will be displayed like this:
["aaaaaaaaaa","bbbbbbbbbbb",..] -- doesn't look like 2D map
which is just syntatic sugar for:
[['a','a','a',..],['b','b','b',..],..] -- looks more like a map now