| Version 2 (modified by jeltsch, 11 months ago) |
|---|
This page is a summary of proposals from #4359
The problem
The current lambda abstraction syntax allows us to conveniently bind parts of the arguments by using patterns, but does not provide a way to branch quickly (without naming the argument). Usually we just cringe a bit and write
\tmp -> case tmp of Pat1 -> ... Pat2 -> ...
or even
\meaningfulName -> case meaningfulName of Pat1 -> ... Pat2 -> ...
However, when this situation nests (e.g. monadic bind) and variables have the same type, naming becomes painful and often degrades to not-so-meaningful meaningfulName1, meaningfulName2, ...
A similar problem exists with proc expressions from arrow notation, which can be regarded as generalized lambda expressions. We sometimes have expressions of the following structure:
proc meaningfulName -> case meaningfulName of
Pat1 -> ...
Pat2 -> ...
Here, the dots stand for arrow expressions, not ordinary expressions.
The proposals
LambdaCase: case of
A simple sugar for one-argument lambda abstractions.
case of Pat1 -> Expr1 Pat2 -> Expr2
desugars to
\freshName -> case freshName of Pat1 -> Expr1 Pat2 -> Expr2
- Pros
- No conflicts with the current syntax (the sequence case of is illegal)
- Cons
- Looks weird (no hint of being a lambda abstraction)
- Single-argument solution (see the note)
- Cannot be generalized to cover also proc expressions
LambdaCase: \case
A "less weird" version of case of. As above,
\case Pat1 -> Expr1 Pat2 -> Expr2
desugars to
\freshName -> case freshName of Pat1 -> Expr1 Pat2 -> Expr2
(\case is a layout herald).
- Pros
- No conflicts with the current syntax (the sequence \ case is illegal)
- An analog syntax for proc expressions can be gained by replacing \ with proc
- Cons
- Single-argument solution (see the note). One way to extend it to support multiple arguments is
\case Pat1_1, Pat1_2, ... -> Expr1 Pat2_1, Pat2_2, ... -> Expr2
(separation with commas is supposed to preserve case-like feel, e.g. Just x, Just y -> vs (Just x) (Just y) ->) which is considered unorthodox by GHC HQ.
- Single-argument solution (see the note). One way to extend it to support multiple arguments is
MultiClauseLambdas
Extend the current syntax with alternative clauses:
\Pat1_1 Pat1_2 ... -> Expr1 Pat2_1 Pat2_2 ... -> Expr2 ...
(\ becomes a layout herald)
- Pros
- Multi-argument solution (see the note)
- An analog syntax for proc expressions can be gained by replacing \ with proc
- Cons
- Breaks current idioms. For example,
mask $ \restore -> do stmt1 stmt2
becomes illegal because stmt1 is indented less than restore. One way to avoid this is to not make \ a herald, forcing users to use explicit layout for multi-clause abstractions, i.e.\ { Pat1_1 Pat1_2 ... -> Expr1 ; Pat2_1 Pat2_2 ... -> Expr2 }
- Breaks current idioms. For example,
MultiClauseLambdas with a keyword
Addresses the layout problem of MultiClauseLambdas. Requires multi-clause abstractions to have a keyword after \:
\KEYWORD Pat1_1 Pat1_2 ... -> Expr1
Pat2_1 Pat2_2 ... -> Expr2
...
(\KEYWORD is a layout herald)
- Pros
- No conflicts with the current syntax
- Multi-argument solution (see the note)
- An analog syntax for proc expressions can be gained by replacing \ with proc
- Cons
- Deciding on the keyword may take years
Extra: LambdaMatch
A full revamp of pattern matching: Haskell' ticket.
Notes
Single vs multi-argument
(field report by Mikhail Vorozhtsov) I've been using \case for over a year and tried MultiClauseLambdas for about two months. In my code base \case seems to cover 99% of cases (no pun intended) and curry $ \case ... does the job for the rest, so having only a single-argument solution may be not as restrictive as it seems. On the other hand, I had a hard time with MultiClauseLambdas extra clauses: I just kept writing Just x -> Expr instead of the correct (Just x) -> Expr. It seems that lines like [spaces]Pat -> Expr are just hardwired to case-expressions in my brain.
