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:
readLinesUntilEmpty :: IO [String]
readLinesUntilEmpty = undefined
An implementation that nearly does this is this:
readLinesUntilEmpty = do
nextLine <- getLine
rest <- readLinesUntilEmpty
return (nextLine : rest)
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):
readLinesUntilEmpty = do
nextLine <- getLine
case nextLine of
"" -> do
undefined -- TODO fix me
_ -> do
undefined -- TODO fix me
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:
joinLines :: [String] -> String
joinLines = undefined -- TODO
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:
combine :: IO (String, String)
combine = do
lines <- readLinesUntilEmpty
let (oddLines, evenLines) = intotwo lines
return $ (joinLines oddLines, joinLines evenLines)
returnmust lift something into the IO monad, which means you have to return a tuple of strings.return.