|
|
# Conditionals and `do`-notation
|
|
|
# The `do`-notation and `if`-`then`-`else`
|
|
|
|
|
|
|
|
|
|
|
|
This page concerns the possibility of tweaking the layout rules to avoid a common pitfall when `if`-`then`-`else` is used with the `do`-notation.
|
|
|
It only documents a problem: no specific solution is proposed. The issue is somewhat related to [NondecreasingIndentation](nondecreasing-indentation).
|
|
|
Strictly speaking, the issue is not tied to the `do`-notation, but that is where it (almost?) always shows up.
|
|
|
|
|
|
|
|
|
## Brief Explanation
|
|
|
|
|
|
<table><tr><th> Ticket </th>
|
|
|
<th>
|
|
|
|
|
|
<table><tr><th>[\#23](https://gitlab.haskell.org//haskell/prime/issues/23)</th>
|
|
|
<td>DoAndIfThenElse</td></tr></table>
|
|
|
|
|
|
Dependencies Related [NondecreasingIndentation](nondecreasing-indentation)Compiler support GHC full (no flag)
|
|
|
nhc98 full (no flag)
|
|
|
Hugs full (no flag)
|
|
|
UHC full (no flag)
|
|
|
JHC full (no flag)
|
|
|
LHC full (no flag)
|
|
|
Brief Explanation
|
|
|
I have lost count of how many times people (including very experienced programmers) have approached me wondering why on earth code like the
|
|
|
following fails to parse:
|
|
|
foo :: Monad m =\> Bool -\> m Int
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
foo :: Monad m => Bool -> m Int
|
|
|
foo x = do
|
|
|
if x then
|
|
|
return 1
|
|
|
else
|
|
|
return 2
|
|
|
```
|
|
|
|
|
|
|
|
|
When I explain that they have to indent the `else` at least one more step, they invariably stare at me in disbelief and vow to henceforth
|
|
|
stay far away from languages where layout has semantic significance. It can actually be somewhat embarassing, and it certainly can
|
|
|
put beginners off.
|
|
|
|
|
|
Strictly speaking, the issue is not tied to the `do`-notation, but that is where it (almost?) always shows up.
|
|
|
Proposal
|
|
|
Change the syntax for conditionals to
|
|
|
|
|
|
exp → `if` exp<sub>1</sub> \[`;`\] `then` exp<sub>2</sub> \[`;`\] `else` exp<sub>3</sub>
|
|
|
i.e., add optional semicolons before `then` and `else`, making the above example legal.
|
|
|
This has been recently added to jhc, GHC and Hugs, and so far it has not caused any problems.
|
|
|
|
|
|
The second optional semicolon is the important one.
|
|
|
The first one just adds a little more convenience.
|
|
|
**Possible addition** (this addition is **not** part of the proposal as accepted for Haskell 2010): Jon Fairbairn suggests that if an optional semicolon is added before `then`, it would be consistent to also add one before `of` in `case` expressions, allowing:
|
|
|
do case whatever
|
|
|
of
|
|
|
blah -\> bluh
|
|
|
blah' -\> bluh'
|
|
|
References[ Conditionals](http://www.haskell.org/onlinereport/exps.html#conditionals) in the Haskell 98 Report
|
|
|
Somewhat related to [NondecreasingIndentation](nondecreasing-indentation)ProsWould address a layout issue that manifestly trips up a lot of people, and many experienced Haskell programmers find very annoying.
|
|
|
Trivial to implement
|
|
|
Independent of the layout rule.
|
|
|
ConsIt has been pointed out that improved error reporting could alleviate this issue to some extent, without
|
|
|
any language change. An alternative might thus be to add a section to the report with recommendations
|
|
|
concerning "best practices" for reporting errors related to this issue and other that are known to
|
|
|
cause confusion.
|
|
|
People might actually write these optional semicolons literally
|
|
|
in their code, thus relying on this hack, making it harder to fix the problem in a better way later.
|
|
|
Download in other formats:[Plain Text](/wiki/DoAndIfThenElse?version=15&format=txt)[](http://trac.edgewall.org/)Powered by [Trac 1.2.2](/about)
|
|
|
|
|
|
By [Edgewall Software](http://www.edgewall.org/).Visit the Trac open source project at
|
|
|
[http://trac.edgewall.com/](http://trac.edgewall.com/)
|
|
|
|
|
|
</th></tr></table> |
|
|
\ No newline at end of file |
|
|
|
|
|
|
|
|
Might it be possible to handle `then` and `else` specially to avoid this problem? At least in the context of `do`?
|
|
|
Or might it be possible to treat `if` as something that opens a kind of explicit layout context (which would
|
|
|
prevent the insertion of a closing `}`) that is closed by a matching `else`?
|
|
|
|
|
|
|
|
|
## References
|
|
|
|
|
|
|
|
|
- Somewhat related to [NondecreasingIndentation](nondecreasing-indentation)
|
|
|
|
|
|
## Pros
|
|
|
|
|
|
|
|
|
- Would address a layout issue that manifestly trips up a lot of people and which at least one
|
|
|
experienced Haskell programmer (me!) finds very annoying.
|
|
|
|
|
|
## Cons
|
|
|
|
|
|
|
|
|
- No concrete proposal yet
|
|
|
- Not implemented in any system to my knowledge |