Reputation: 9360
I am reading Real World Haskell and i can not understand when is the result of the break
method evaluated.
If it starts with the pre:case suf of
clause then it has to go in the let clause fetch the tuple that break
method generates and then treat the case expression?
Or how does it do it?
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'
Is it :
1.Goes into pre:case suf of
2.Goes to let clause determines what pre
and suf
are
3.glues up pre
and suf
and then treats the case expression?
Or what is the order for constructing the case expression?
Upvotes: 1
Views: 95
Reputation: 233125
In principle, all Haskell functions are defined using a single expression (at least, if you ignore do
syntax). Contrary to statement-based languages like the C family, a function is just an expression.
Sometimes, though, it can enhance readability if you can break up a function definition in two or more sub-steps. Haskell's let...in
syntax enables you to do that.
let
lets you define one or more names that you can then reference in the in
expression. You can define as many names as you want in the let
part, but the in
part must still be a single expression.
Another option is to use where
. You can rewrite the splitLines
function using where
syntax instead:
splitLines [] = []
splitLines cs =
pre : case suf of
('\r':'\n':rest) -> splitLines rest
('\r':rest) -> splitLines rest
('\n':rest) -> splitLines rest
_ -> []
where (pre, suf) = break isLineTerminator cs
isLineTerminator c = c == '\r' || c == '\n'
In both cases, the expression of splitLines
conses pre
unto the expression starting with case suf of
.
In order to be able to do that, it'll first have to evaluate pre
and suf
, which are both defined by the expression break isLineTerminator cs
. So, in order to evaluate pre
and suf
, the overall function evaluates break isLineTerminator cs
.
It now knows what pre
and suf
is, so it can evaluate the rest of the case
expression and cons the result of that with pre
.
Notice that splitLines
is recursive, so this'll keep on happening until splitLines
hits the base case []
.
Recall that Haskell is lazily evaluated, so all of this only happens just-in-time, when a result is required.
Upvotes: 3
Reputation: 23004
It’s impossible to say how it’s evaluated unless you specify how the result of splitLines
is going to be used. Lazy evaluation does as little as possible. E.g., if you test the result with null
then break
is never called. If you take the head and use that, break
is called, but the case
is never evaluated. And so on.
Upvotes: 7