I’ve dabbled with Haskell in the past, and recently got back into it seriously, and I’m reading real world haskell. Some of the examples they’ve shone, I’ve yet to understand. Such at this one:
myLength [] = 0
myLength (x:xs) = 1 + myLength (xs)
I don’t see how this works, what is 1 really being added too? How is the recursion returning something that can be added to? I don’t get it.
And here we have this one:
splitLines [] = []
splitLines cs =
let (pre, suf) = break isLineTerminator cs
in pre : case suf of
('\r':'\n':rest) -> splitLines rest
('\r':rest) -> splitLines rest
('\n':rest) -> splitLines rest
_ -> []
isLineTerminator c = c == '\r' || c == '\n'
How does this work, what is pre really being attached too? I don’t see how the the result of the case expression is something that pre can be concatenated to. Maybe I just need someone to explain the evaluation of these functions in details. I must be missing something very vital.
Thanks in advance!
EDIT: I know, it was a copy-paste fail. Sorry.
EDIT 2: It seems my confusion was with what these functions were actually /returning/ I have it all worked out now. Thanks for the answers guys, it finally clicked! I appreciate it!
As for the first one, it’s a very basic way of recursion. However, it seems to be missing a part:
It works by scaling off one element at the time from the list and adding one to the result. To visualise, consider the call
which will evaluate to:
which is 3.
As for the second one, well, you have already split the string at the next line break into two parts: pre and suf. Now, suf will start with either a \n, or a \r, or a \r\n. We want to remove these. So we use pattern matching. See how the rest variable is essentially the suf variable minus the initial line break character(s).
So we have pre, which is the first line, and rest, which is the rest of the text. So in order to continue splitting rest into lines we call splitLines on it recursively and concatenate the result to pre.
To visualize, say you have the string “foo\nbar\r\nbaz”.
So, when calling, the result will be:
then splitLines is called again, and the result is expanded into:
then once again:
which is the final result.