Your track variable was actually a list of single lines, not a line with '\n' . Since you have already divided it into lines , you can simply map readLine above it by specifying:
readTrack str = parseTrack (lines str) where parseTrack (start:finish:tracks) = (map readLine tracks, readPoint start, readLine finish)
Here tracks :: [String] , so you can map readLine to all of them - you do not need to use readLines to split it into lines first. (You can tell him the list because this is the last thing on the right side : )
You speak
However, what I think is happening because the finish is the top item from the list, and start gets the designated top char from this line.
Well, what happened: because you requested readLines track as the first output, Haskell started there, and since you announced
readLines :: String -> [Line]
which meant that track was supposed to be String - this is the only thing readLines can read.
First, you need to remember that : has an element on the left and right on the right, so in
3:4:stuff
stuff must be [Integer] because it is to the right of some Integer elements. Similarly
c:"a string"
means c must be char because String = [Char].
In your code, we found out that track is a string, so that means when writing
(start : finish : track)
both the beginning and the end must be elements that you can put before the line, so the beginning and the end must be Char.
Haskell then looks at your readPoint start code, but because it has start type Char, but
readPoint :: String -> Point
he complains that char and String do not match.
I think you made a mistake because you forgot that readLines takes one line, but she felt (on behalf of) that she should happily take a list of lines. Your parseLines look as if it looks like a similar thing, but it takes a list of lines, so it copies, while readLines takes one line with newline characters, so it cannot handle the list.