On Thu, Jul 27, 2006 at 10:22:31AM +0100, Jon Fairbairn wrote:
> On 2006-07-27 at 01:33EDT Paul Hudak wrote:
> > Thanks for asking about this -- it probably should be in the paper. Dan
> > Doel's answer is closest to the truth:
> >
> > I imagine the answer is that having the syntax for it looks nicer/is
> > clearer. "if a b c" could be more cryptic than "if a then b else c"
> > for some values of a, b and c.
> >
> > except that there was also the simple desire to conform to convention
> > here (I don't recall fewer parentheses being a reason for the choice).
>> In a sense, it explicitly wasn't: I suggested "if _ then _
> else _ fi" -- something I was long used to from Algol68 --
> but it was rejected on the ground that there wasn't a
> dangling else problem in Haskell.
But because if-then-else is an expression, there is another
problem. Consider:
(if True then 0 else 1) + 2 --> 2
if True then 0 else 1 + 2 --> 0
let cond a b c = if a then b else c
cond True 0 1 + 2 --> 2 -- different from if-then-else withouth parentheses
It's quite easy to fall in this trap. I think it happened to me
at least twice. It goes like this: first I have an expression
that doesn't involve if-then-else, eg.
a + b
Then I realize that "a" has to be changed in some situations,
so I replace it with a conditional expression:
if c then a else a' + b
or
if c then f a else g a + b
But now " + b" gets under the "else" branch.
If I used a "cond" function, or if if-then-else had a different
priority, it would be easier to avoid such a mistake. There is no
problem with the first version:
cond c a a' + b
For an experienced Haskell programmer it's obvious that function
application has a higher precendence than addition.
In the second version, it would be clear that parentheses have
to be added:
cond c (f a) (g a) + b
Could the "cond" function encourage other kinds of bugs? I think
it's less likely, because it's a normal function.
Also, after a few years of Haskell programming, I am still not
sure how to indent if-then-else.
Perhaps in Haskell' we could have some lightweight case-of version with
no pattern matching, guards only ("cond" could be a good name). I think
it was even discussed before. The usual case-of looks like this:
case x of
Left err | isEOFError e -> ...
Left err -> ...
Right result -> ...
"cond" would involve no pattern matching, or only as pattern guards.
cond
x == 0 -> ...
x == 1 -> ...
otherwise -> ...
currently it can be written as
case () of
_ | x == 0 -> ...
_ | x == 1 -> ...
_ | otherwise -> ...
which is a bit ugly.
Best regards
Tomasz