It is a part of a homework.
I need to write a function that reads info from the input until empty line. After that function puts first, third, fifth … line symbols as one String and second, fourth … as another String.
Signature is combine :: IO (String , String)
I have written a function that takes a list as argument and puts 1,3,5.. to one String a 2,4,6 symbols to another String. Function is here:
intotwo (x : xs)
= let
(us , vs)
= intotwo xs
in
(x : vs , us)
intotwo _
= ([] , [])
Also I have written a code that reads an input: It is here:
combine
= do
lines <- getLine
if null lines
then return ([], [])
else do
linesagain <- combine
return --what should I return?
Can anybody help me to finish my homework (optional: give some tips)?
I’ll give a few hints to help you solve your problem.
Firstly, it is a HUGE help to give types to all the functions you define. This lets the compiler tell you immediately if a function isn’t doing what you think it is doing. It also helps you when you need to join different parts of your program together.
Secondly, it is a very good idea to only solve one problem per function. Your intotwo function follows this well, it does its job of splitting a list very well. Your combine function however looks like it is trying to do too much, which will make it harder to write. I would split that function into two smaller functions.
Finally, there is a very useful special function called
undefined. This matches any type, and helps you write a function. The trick is to start with the whole function equalling undefined (and compiling but crashing when run), and progressively improve the function until it does what you want and has no more undefines in it.So firstly, I would add a type signature to the intotwo function. THe type is
[a] -> ([a], [a]).Next, I would write a function that reads lines from input until it hits an empty line, then returns the list of lines read. This function would have the type:
An implementation that nearly does this is this:
However this never stops reading (note how nextLine isn’t checked for being empty).
the following function shows how you can do this (but I’m leaving some of the implementation out):
You should be able to figure out the rest from there.
Next, your intotwo function returns two lists of strings, but you are expected to join them together again. Eg
["this", "that"]should turn into"this\nthat". The type of such a function is[String] -> String:This is an easier function to write than the inttotwo func, so you should be fine.
Finally, you can link those three functions together to get your result: