wiki:MultiWayIf

Version 5 (modified by malcolm.wallace@…, 8 years ago) (diff)

--

Very often I find myself wanting to write an if-then-else with multiple branches. This is one expression form that isn't catered for well at the moment. Using nested 'if' is unsatisfactory because the nesting grows with each branch, and all those keywords are quite syntactically heavy.

One idiom that is often used for this is:

case () of
  _ | pred1 -> e1
    ...
    | predn -> en

this is very powerful in conjunction with PatternGuards, incidentally. But it's ugly. I propose a simpler form:

case | pred1 -> e1
     ...
     | predn -> en

There are no syntactic problems with this because it is uniquely identified by the sequence 'case |' which is currently not a valid expression prefix in Haskell. It's therefore backwards compatible.

Semantics can be defined as shorthand for the original case statement above.

Cons: it isn't implemented anywhere.

see also

Observations

Currently, guards are permitted at the definition clause level. But this proposal can be viewed as permitting guards at the expression level too. In the spirit of reducing unnecessary duplication, it would then be possible to remove definition-level guards from the language. The current form

foo (x:xs)
    | x < n  = ...
    | x > n  = ...

can be straightforwardly replaced by

foo (x:xs) = case
    | x < n  -> ...
    | x > n  -> ...

Note the change in the equals sign, from one per guard to one per clause. Case-style alternatives use -> instead of =. However, this removal would break old programs.

Bogosity alert. The above observation is incorrect. If all the definition-level guards are false, pattern-matching will fall through to the next clause or case-pattern. But in the expression-level guards, this is not the case. Intuitively, once you "cross the equals sign" from lhs to rhs of a definition, you are committed to that equation and cannot back-track.