How do I read N lines in a file with Haskell? - haskell

I have a file in the form:
3
1 2
3 4
5 7
Where the first line is the number of lines
I know that:
getInt :: IO Int
getInt = readLn
main = do num <- getInt
print (num)
Reads the first line.
Next, I tried:
readInts :: IO [Int]
readInts = fmap (map read.words) getLine
For read a line and get a list: [a,b].
And I tried to use the above in a recursive loop
loop :: Int -> IO()
loop n = if 1 == n then do num <- readInts
print(num)
else loop (n-1)
I'm getting the first line only:
[5,3]
But I need to read the rest of lines, given N

The format of the input file looks a lot like the ones used in programming contests. Here is my standard setup for programming contests like that:
import Control.Monad
import Text.Printf
main :: IO ()
main = do
n <- readLn
forM_ [1 .. n] $ \i -> do
printf "Case %d: " (i :: Int)
solve
An example of solve might be:
solve :: IO ()
solve = do
nums <- map read . words <$> getLine
print (sum nums)

Adding to this helpful answer and comment, for some challenges you'll need to collect n lines and then emit a single result at the end based on an aggregation of the data. An approach for creating a list might use replicateM as follows:
import Control.Monad
toInt :: String -> Int
toInt x = read x :: Int
lineToInts :: String -> [Int]
lineToInts x = map toInt $ words x
main :: IO ()
main = do
n <- readLn
remainingLines <- replicateM n getLine
let list = map lineToInts remainingLines
print list
Sample run:
3
0 1
3 4
6 8
[[0,1],[3,4],[6,8]]
See also Read n lines input with Haskell

Have you looked into the function lines? It takes a string and returns the same string as a list separated by \n. Using this function you don't even have to have the number of lines.

Related

Can we access the output from a replicateM defined in a do-block

Assume i have something like this
main = do
input_line <- getLine
let n = read input_line :: Int
replicateM n $ do
input_line <- getLine
let x = read input_line :: Int
return ()
***putStrLn $ show -- Can i access my replicateM here?
return ()
Can i access the result of my replicateM such as if it was a returned value, and for example print it out. Or do i have to work with the replicateM inside the actual do-block?
Specialized to IO
replicateM :: Int -> IO a -> IO [a]
which means that it returns a list. So in your example you could do:
results <- replicateM n $ do
input_line <- getLine
let x = read input_line :: Int
return x -- <- we have to return it if we want to access it
print results
replicateM n a returns a list of the values returned by a. In your case that'd just be a list of units because you have the return () at the end, but if you replace that with return x, you'll get a list of the read integers. You can then just use <- to get it out of the IO.
You can also simplify your code by using readLine instead of getLine and read. Similarly putStrLn . show can be replaced with print.
main = do
n <- readLn
ints <- replicateM n readLn :: IO [Int]
print ints
Of course. Its type is replicateM :: Monad m => Int -> m a -> m [a]. It means it can appear to the right of <- in a do block:
do
....
xs <- replicateM n $ do { ... }
....
xs will be of type [a], as usual for binding the results from Monad m => m [a].
With your code though, where you show return () in that nested do, you'll get ()s replicated n times in your xs. Presumably in the real code you will return something useful there.

Handling complicated input (with nested values)

There is the following task:
First line is the number of cases
For each case there is a line with the number of numbers to add
For each case there is also a line with the numbers
For each case I have to print summed numbers
Example:
Input:
2
5
1 2 3 4 5
2
-100 100
Output:
15
0
This is my implementation
import Control.Monad
main = do
linesCount <- readLn :: IO Int
numbers <- replicateM linesCount getCase
mapM_ putStrLn $ map (show.sum) numbers
getCase :: IO [Int]
getCase = do
numbersCount <- readLn :: IO Int -- actually I don't need this variable
numbersString <- getLine
let numbers = map read $ words numbersString
return numbers
It looks like a lot of code for parsing input. Are there any tricks to "compress" it? :)
If you merely want to make code shorter then check out the Stack Exchange community for code golfing. That is primarily for fun and games.
If we are thinking there is too much code it may not be that we need to make it shorter but rather that we need to make it clearer. Achieving this is a matter of experience and good practice. What we want to do is isolate simple concepts which are obviously correct and then combine them in obviously correct ways. Methodologies include top-down design (break the solution into smaller pieces) and bottom-up design (from smaller pieces build up to the solution) and mixes thereof.
A bottom-up piece that hits me straight away is the task of summing a list of numbers. This has a definition in Haskell's Prelude called sum :: (Num a, Foldable t) => t a -> a. Somewhere in the final solution we are going to use this.
Another method is to simplify the problem. We can be lead astray by the way a problem is phrased. Upon closer inspection we might find an equivalent and simpler phrasing.
What information do we actually need from the input? Just the lists of numbers. What is the simplest way to obtain the lists of numbers? The number of lists seems irrelevant because there is no need to have this information before we start looking at the lists. Drop the first line and we are left with:
5
1 2 3 4 5
2
-100 100
Then, the length of each list is also irrelevant because we do not need that information before summing the list. Therefore lets also drop every other line from this point:
1 2 3 4 5
-100 100
Now we just have the lists of numbers separated by line returns where each number is separated by a space.
At this point we have a clear way to break apart the solution in a top-down manner. First we simplify the input. Secondly we parse the lists of numbers. Thirdly we sum the lists. Fourthly we print the sums. This is therefore the skeleton of our solution:
simplifyInput :: String -> [String]
parseNumberList :: String -> [Integer]
-- Note we can use `sum` from Prelude to sum the number lists.
printSums :: [Integer] -> IO ()
main :: IO ()
main = getContents >>= printSums . fmap (sum . parseNumberList) . simplifyInput
Now it is just a matter of implementing each obvious piece of the solution.
simplifyInput :: String -> [String]
simplifyInput = dropEveryOther . drop 1 . lines
where
dropEveryOther :: [a] -> [a]
In writing simplifyInput I discovered that dropping every other line requires some more work. That is okay, we can just break the solution apart again.
dropEveryOther :: [a] -> [a]
dropEveryOther [] = []
dropEveryOther (x:y:xs) = y : dropEveryOther xs
Then continuing...
parseNumberList :: String -> [Integer]
parseNumberList = fmap read . words
printSums :: [Integer] -> IO ()
printSums = putStr . unlines . fmap show
Therefore, in totality:
simplifyInput :: String -> [String]
simplifyInput = dropEveryOther . drop 1 . lines
where
dropEveryOther :: [a] -> [a]
dropEveryOther [] = []
dropEveryOther (_:y:xs) = y : dropEveryOther xs
parseNumberList :: String -> [Integer]
parseNumberList = fmap read . words
printSums :: [Integer] -> IO ()
printSums = putStr . unlines . fmap show
main :: IO ()
main = getContents >>= printSums . fmap (sum . parseNumberList) . simplifyInput
The amount of code we have has gone up (compared to the first solution) but in exchange the code is made obvious. Now you should add some documentation comments so we do not forget our explanation for the solution.
Alec posted a super compressed version of my original code in one of the comments. I decided to post a small breakdown, in case someone gets lost and has no idea what's going on in there :)
Snippets below need to be preceded with valid imports:
import Control.Monad
import Control.Applicative
So we start with Alec's version:
main = readLn >>= flip replicateM_ (getLine >> sum . map read . words <$> getLine >>= print)
He used the flip function in order to remove one set of parenthesis:
main = readLn >>= (`replicateM_` (getLine >> (print =<< sum . map read . words <$> getLine)))
He used the infix notation for replicateM_ in order to partially apply the second parameter of replicateM_, we can replace is with a lambda:
main = readLn >>= \n -> replicateM_ n (getLine >> (print =<< sum . map read . words <$> getLine))
Now let's start extracting some pieces of code into separate meaningful functions:
printBatchResult = print =<< sum . map read . words <$> getLine
main = readLn >>= \n -> replicateM_ n (getLine >> printBatchResult)
We can flip the print =<< for more readability:
printBatchResult = sum . map read . words <$> getLine >>= print
main = readLn >>= \n -> replicateM_ n (getLine >> printBatchResult)
And so on:
printBatchResult = sum . map read . words <$> getLine >>= print
handleBatch = getLine >> printBatchResult
main = readLn >>= \n -> replicateM_ n handleBatch
And again:
sumLine = sum . map read . words
printBatchResult = sumLine <$> getLine >>= print
handleBatch = getLine >> printBatchResult
main = readLn >>= \n -> replicateM_ n handleBatch
And one more time:
sumLine = sum . map read . words
handleNumbersLine = sumLine <$> getLine
printBatchResult = handleNumbersLine >>= print
handleBatch = getLine >> printBatchResult
main = readLn >>= (\n -> replicateM_ n handleBatch)
And finally the last time:
sumLine = sum . map read . words
handleNumbersLine = sumLine <$> getLine
printBatchResult = handleNumbersLine >>= print
handleBatch = getLine >> printBatchResult
handleAllBatches n = replicateM_ n handleBatch
main = readLn >>= handleAllBatches
We can replace <$> with fmap:
sumLine = sum . map read . words
handleNumbersLine = fmap sumLine getLine
printBatchResult = handleNumbersLine >>= print
handleBatch = getLine >> printBatchResult
handleAllBatches n = replicateM_ n handleBatch
main = readLn >>= handleAllBatches
We can also remove every partial application:
sumLine line = (sum . map read . words) line
handleNumbersLine = fmap sumLine getLine
printBatchResult = handleNumbersLine >>= \sum -> print sum
handleBatch = getLine >> printBatchResult
handleAllBatches n = replicateM_ n handleBatch
main = readLn >>= \numberOfBatches -> handleAllBatches numberOfBatches
And finally, add signatures:
sumLine :: String -> Int
sumLine line = (sum . map read . words) line
handleNumbersLine :: IO Int
handleNumbersLine = fmap sumLine getLine
printBatchResult :: IO ()
printBatchResult = handleNumbersLine >>= \sum -> print sum
handleBatch :: IO ()
handleBatch = getLine >> printBatchResult
handleAllBatches :: Int -> IO ()
handleAllBatches n = replicateM_ n handleBatch
main = readLn >>= \numberOfBatches -> handleAllBatches numberOfBatches
Some final comments:
>>= - the bind function from monad converts one monad to another (or the same) and transforms its value. In main function it takes IO Int, transformation lambda and returns IO () - the result of the transformation, which is empty and prints result in the process.
>> - (used in handleBatch) ignores the left parameter (how many numbers there are in a line is (arguably) unnecessary) and just returns the right parameter - which is a function handling a line with numbers.

Technique for reading in multiple lines for Haskell IO

Basically I would like to find a way so that a user can enter the number of test cases and then input their test cases. The program can then run those test cases and print out the results in the order that the test cases appear.
So basically I have main which reads in the number of test cases and inputs it into a function that will read from IO that many times. It looks like this:
main = getLine >>= \tst -> w (read :: String -> Int) tst [[]]
This is the method signature of w: w :: Int -> [[Int]]-> IO ()
So my plan is to read in the number of test cases and have w run a function which takes in each test case and store the result into the [[]] variable. So each list in the list will be an output. w will just run recursively until it reaches 0 and print out each list on a separate line. I'd like to know if there is a better way of doing this since I have to pass in an empty list into w, which seems extraneous.
As #bheklilr mentioned you can't update a value like [[]]. The standard functional approach is to pass an accumulator through a a set of recursive calls. In the following example the acc parameter to the loop function is this accumulator - it consists of all of the output collected so far. At the end of the loop we return it.
myTest :: Int -> [String]
myTest n = [ "output line " ++ show k ++ " for n = " ++ show n | k <- [1..n] ]
main = do
putStr "Enter number of test cases: "
ntests <- fmap read getLine :: IO Int
let loop k acc | k > ntests = return $ reverse acc
loop k acc = do
-- we're on the kth-iteration
putStr $ "Enter parameter for test case " ++ show k ++ ": "
a <- fmap read getLine :: IO Int
let output = myTest a -- run the test
loop (k+1) (output:acc)
allOutput <- loop 1 []
print allOutput
As you get more comfortable with this kind of pattern you'll recognize it as a fold (indeed a monadic fold since we're doing IO) and you can implement it with foldM.
Update: To help explain how fmap works, here are equivalent expressions written without using fmap:
With fmap: Without fmap:
n <- fmap read getLine :: IO [Int] line <- getLine
let n = read line :: Int
vals <- fmap (map read . words) getLine line <- getLine
:: IO [Int] let vals = (map read . words) line :: [Int]
Using fmap allows us to eliminate the intermediate variable line which we never reference again anyway. We still need to provide a type signature so read knows what to do.
The idiomatic way is to use replicateM:
runAllTests :: [[Int]] -> IO ()
runAllTests = {- ... -}
main = do
numTests <- readLn
tests <- replicateM numTests readLn
runAllTests tests
-- or:
-- main = readLn >>= flip replicateM readLn >>= runAllTests

How to do something with data from stdin, line by line, a maximum number of times and printing the number of line in Haskell

This code reads the number of lines to process from the first line of stdin, then it loops number_of_lines_to_process times doing some calculations and prints the result.
I want it to print the line number in "Line #" after "#" but I don't know how to obtain it
import IO
import Control.Monad (replicateM)
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let number_of_lines_to_process = read s :: Integer
lines <- replicateM (fromIntegral(number_of_lines_to_process)) $ do
line <- getLine
let number = read line :: Integer
result = number*2 --example
putStrLn ("Line #"++": "++(show result)) --I want to print the number of the iteration and the result
return ()
I guess that the solution to this problem is really easy, but I'm not familiar with Haskell (coding in it for the first time) and I didn't find any way of doing this. Can anyone help?
You could use forM_ instead of replicateM:
import IO
import Control.Monad
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let number_of_lines_to_process = read s :: Integer
forM_ [1..number_of_lines_to_process] (\i -> do
line <- getLine
let number = read line :: Integer
result = number * 2
putStrLn $ "Line #" ++ show i ++ ": " ++ show result)
Note that because you use forM_ (which discards the results of each iteration) you don't need the additional return () at the end - the do block returns the value of the last statement, which in this case is the () which is returned by forM_.
The trick is to first create a list of all the line numbers you want to print, and to then loop through that list, printing each number in turn. So, like this:
import Control.Monad
import System.IO
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let lineCount = read s :: Int
-- Create a list of the line numbers
lineNumbers = [1..lineCount]
-- `forM_` is like a "for-loop"; it takes each element in a list and performs
-- an action function that takes the element as a parameter
forM_ lineNumbers $ \ lineNumber -> do
line <- getLine
let number = read line :: Integer
result = number*2 --example
putStrLn $ "Line #" ++ show lineNumber ++ ": " ++ show result
return ()
Read the definition of forM_.
By the way, I wouldn't recommend using the old Haskell98 IO library. Use System.IO instead.
You could calculate the results, enumerate them, and then print them:
import IO
import Control.Monad (replicateM)
-- I'm assuming you start counting from zero
enumerate xs = zip [0..] xs
main :: IO ()
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let number_of_lines_to_process = read s :: Integer
lines <- replicateM (fromIntegral(number_of_lines_to_process)) $ do
line <- getLine
let number = read line :: Integer
result = number*2 --example
return result
mapM_ putStrLn [ "Line "++show i++": "++show l | (i,l) <- enumerate lines ]
I'm still new at Haskell, so there could be problems with the program below (it does work). This program is a tail recursive implementation. The doLine helper function carries around the line number. The processing step is factored into process, which you can change according to the problem you are presented.
import System.IO
import Text.Printf
main = do
hSetBuffering stdin LineBuffering
s <- getLine
let number_of_lines_to_process = read s :: Integer
processLines number_of_lines_to_process
return ()
-- This reads "max" lines from stdin, processing each line and
-- printing the result.
processLines :: Integer -> IO ()
processLines max = doLine 0
where doLine i
| i == max = return ()
| otherwise =
do
line <- getLine
let result = process line
Text.Printf.printf "Line #%d: %d\n" (i + 1) result
doLine (i + 1)
-- Just an example. (This doubles the input.)
process :: [Char] -> Integer
process line = let number = read line :: Integer
in
number * 2
I'm a haskell rookie, so any critiques of the above are welcome.
Just as an alternative, I thought that you might enjoy an answer with minimal monad mucking and no do notation. We zip a lazy list of the user's data with an infinite list of the line number using the enumerate function to give us our desired output.
import System.IO
import Control.Monad (liftM)
--Here's the function that does what you really want with the data
example = (* 2)
--Enumerate takes a function, a line number, and a line of input and returns
--an ennumerated line number of the function performed on the data
enumerate :: (Show a, Show b, Read a) => (a->b) -> Integer -> String -> String
enumerate f i x = "Line #" ++
show i ++
": " ++
(show . f . read $ x) -- show . f . read handles our string conversion
-- Runover takes a list of lines and runs
-- an enumerated version of the sample over those lines.
-- The first line is the number of lines to process.
runOver :: [String] -> [String]
runOver (line:lines) = take (read line) $ --We only want to process the number of lines given in the first line
zipWith (enumerate example) [1..] lines -- run the enumerated example
-- over the list of numbers and the list of lines
-- In our main, we'll use liftM to lift our functions into the IO Monad
main = liftM (runOver . lines) getContents

How do I parse a matrix of integers in Haskell?

So I've read the theory, now trying to parse a file in Haskell - but am not getting anywhere. This is just so weird...
Here is how my input file looks:
m n
k1, k2...
a11, ...., an
a21,.... a22
...
am1... amn
Where m,n are just intergers, K = [k1, k2...] is a list of integers, and a11..amn is a "matrix" (a list of lists): A=[[a11,...a1n], ... [am1... amn]]
Here is my quick python version:
def parse(filename):
"""
Input of the form:
m n
k1, k2...
a11, ...., an
a21,.... a22
...
am1... amn
"""
f = open(filename)
(m,n) = f.readline().split()
m = int(m)
n = int(n)
K = [int(k) for k in f.readline().split()]
# Matrix - list of lists
A = []
for i in range(m):
row = [float(el) for el in f.readline().split()]
A.append(row)
return (m, n, K, A)
And here is how (not very) far I got in Haskell:
import System.Environment
import Data.List
main = do
(fname:_) <- getArgs
putStrLn fname --since putStrLn goes to IO ()monad we can't just apply it
parsed <- parse fname
putStrLn parsed
parse fname = do
contents <- readFile fname
-- ,,,missing stuff... ??? how can I get first "element" and match on it?
return contents
I am getting confused by monads (and the context that the trap me into!), and the do statement. I really want to write something like this, but I know it's wrong:
firstLine <- contents.head
(m,n) <- map read (words firstLine)
because contents is not a list - but a monad.
Any help on the next step would be great.
So I've just discovered that you can do:
liftM lines . readFile
to get a list of lines from a file. However, still the example only only transforms the ENTIRE file, and doesn't use just the first, or the second lines...
The very simple version could be:
import Control.Monad (liftM)
-- this operates purely on list of strings
-- and also will fail horribly when passed something that doesn't
-- match the pattern
parse_lines :: [String] -> (Int, Int, [Int], [[Int]])
parse_lines (mn_line : ks_line : matrix_lines) = (m, n, ks, matrix)
where [m, n] = read_ints mn_line
ks = read_ints ks_line
matrix = parse_matrix matrix_lines
-- this here is to loop through remaining lines to form a matrix
parse_matrix :: [String] -> [[Int]]
parse_matrix lines = parse_matrix' lines []
where parse_matrix' [] acc = reverse acc
parse_matrix' (l : ls) acc = parse_matrix' ls $ (read_ints l) : acc
-- this here is to give proper signature for read
read_ints :: String -> [Int]
read_ints = map read . words
-- this reads the file contents and lifts the result into IO
parse_file :: FilePath -> IO (Int, Int, [Int], [[Int]])
parse_file filename = do
file_lines <- (liftM lines . readFile) filename
return $ parse_lines file_lines
You might want to look into Parsec for fancier parsing, with better error handling.
*Main Control.Monad> parse_file "test.txt"
(3,3,[1,2,3],[[1,2,3],[4,5,6],[7,8,9]])
An easy to write solution
import Control.Monad (replicateM)
-- Read space seperated words on a line from stdin
readMany :: Read a => IO [a]
readMany = fmap (map read . words) getLine
parse :: IO (Int, Int, [Int], [[Int]])
parse = do
[m, n] <- readMany
ks <- readMany
xss <- replicateM m readMany
return (m, n, ks, xss)
Let's try it:
*Main> parse
2 2
123 321
1 2
3 4
(2,2,[123,321],[[1,2],[3,4]])
While the code I presented is quite expressive. That is, you get work done quickly with little code, it has some bad properties. Though I think if you are still learning haskell and haven't started with parser libraries. This is the way to go.
Two bad properties of my solution:
All code is in IO, nothing is testable in isolation
The error handling is very bad, as you see the pattern matching is very aggressive in [m, n]. What happens if we have 3 elements on the first line of the input file?
liftM is not magic! You would think it does some arcane thing to lift a function f into a monad but it is actually just defined as:
liftM f x = do
y <- x
return (f y)
We could actually use liftM to do what you wanted to, that is:
[m,n] <- liftM (map read . words . head . lines) (readFile fname)
but what you are looking for are let statements:
parseLine = map read . words
parse fname = do
(x:y:xs) <- liftM lines (readFile fname)
let [m,n] = parseLine x
let ks = parseLine y
let matrix = map parseLine xs
return (m,n,ks,matrix)
As you can see we can use let to mean variable assignment rather then monadic computation. In fact let statements are you just let expressions when we desugar the do notation:
parse fname =
liftM lines (readFile fname) >>= (\(x:y:xs) ->
let [m,n] = parseLine x
ks = parseLine y
matrix = map parseLine xs
in return matrix )
A Solution Using a Parsing Library
Since you'll probably have a number of people responding with code that parses strings of Ints into [[Int]] (map (map read . words) . lines $ contents), I'll skip that and introduce one of the parsing libraries. If you were to do this task for real work you'd probably use such a library that parses ByteString (instead of String, which means your IO reads everything into a linked list of individual characters).
import System.Environment
import Control.Monad
import Data.Attoparsec.ByteString.Char8
import qualified Data.ByteString as B
First, I imported the Attoparsec and bytestring libraries. You can see these libraries and their documentation on hackage and install them using the cabal tool.
main = do
(fname:_) <- getArgs
putStrLn fname
parsed <- parseX fname
print parsed
main is basically unchanged.
parseX :: FilePath -> IO (Int, Int, [Int], [[Int]])
parseX fname = do
bs <- B.readFile fname
let res = parseOnly parseDrozzy bs
-- We spew the error messages right here
either (error . show) return res
parseX (renamed from parse to avoid name collision) uses the bytestring library's readfile, which reads in the file packed, in contiguous bytes, instead of into cells of a linked list. After parsing I use a little shorthand to return the result if the parser returned Right result or print an error if the parser returned a value of Left someErrorMessage.
-- Helper functions, more basic than you might think, but lets ignore it
sint = skipSpace >> int
int = liftM floor number
parseDrozzy :: Parser (Int, Int, [Int], [[Int]])
parseDrozzy = do
m <- sint
n <- sint
skipSpace
ks <- manyTill sint endOfLine
arr <- count m (count n sint)
return (m,n,ks,arr)
The real work then happens in parseDrozzy. We get our m and n Int values using the above helper. In most Haskell parsing libraries we must explicitly handle whitespace - so I skip the newline after n to get to our ks. ks is just all the int values before the next newline. Now we can actually use the previously specified number of rows and columns to get our array.
Technically speaking, that final bit arr <- count m (count n sint) doesn't follow your format. It will grab n ints even if it means going to the next line. We could copy Python's behavior (not verifying the number of values in a row) using count m (manyTill sint endOfLine) or we could check for each end of line more explicitly and return an error if we are short on elements.
From Lists to a Matrix
Lists of lists are not 2 dimensional arrays - the space and performance characteristics are completely different. Let's pack our list into a real matrix using Data.Array.Repa (import Data.Array.Repa). This will allow us to access the elements of the array efficiently as well as perform operations on the entire matrix, optionally spreading the work among all the available CPUs.
Repa defines the dimensions of your array using a slightly odd syntax. If your row and column lengths are in variables m and n then Z :. n :. m is much like the C declaration int arr[m][n]. For the one dimensional example, ks, we have:
fromList (Z :. (length ks)) ks
Which changes our type from [Int] to Array DIM1 Int.
For the two dimensional array we have:
let matrix = fromList (Z :. m :. n) (concat arr)
And change our type from [[Int]] to Array DIM2 Int.
So there you have it. A parsing of your file format into an efficient Haskell data structure using production-oriented libraries.
What about something simple like this?
parse :: String -> (Int, Int, [Int], [[Int]])
parse stuff = (m, n, ks, xss)
where (line1:line2:rest) = lines stuff
readMany = map read . words
(m:n:_) = readMany line1
ks = readMany line2
xss = take m $ map (take n . readMany) rest
main :: IO ()
main = do
stuff <- getContents
let (m, n, ks, xss) = parse stuff
print m
print n
print ks
print xss

Resources