The only reason to keep semicolons I can think of is to look familiar to C programmers, so as not to scare them off. I’m not very familiar with that demographic, but I think most of them would be fine with it, especially if they have used other semicolon-less languages. Semicolons, which are present on about 50% of lines, add visual noise and the cognitive load of remembering to type them.
Think of it like a sliding scale: on the far extreme of no redundancy, a typo could be a runtime error instead of a compile error. On the far extreme of redundancy, you have to express your code twice in different ways. Having semicolons is a reasonable balance between the extremes.
Semicolons help get a better error message for the following typo, if `foo` can take either 0 or 1 arguments:
if (true) {
foo(;
bar *= 2;
baz(
"first",
"second",
);
}
The compiler can easily tell you that you forgot a ) on line 2. If semicolons were optional, the program would be this: if (true) {
foo(
bar *= 2
baz(
"first",
"second",
)
}
The simplest error message to implement would complain that you forgot a ) somewhere within lines 2 to 7, and also that the argument to `foo` contains two statements instead of one expression. This error message would be less helpful.However, with the semicolonless language, you could still write the compiler to give the better error message. You could have a heuristic that that this combination of errors suggests a different error, or you could parse indentation for error-checking purposes. It would just require more work on the part of the compiler writer.
Otherwise, it's one of those things that you don't realize how useful it is until you can't do it. But not often, and ideally a Sufficiently Expressive Language wouldn't need code generation—but this is targeting C's niche, not Haskell's.