|
|
`-Wredundant-bang-patterns` is an extra sanity check that warns when bang pattern is unnecessary. Usually this is the case when the value being pattern matched against is already in WHNF. Of course there are a few tricky cases, most notably dealing with values of unlifted types.
|
|
|
|
|
|
### Motivation
|
|
|
The programmer might expect that `!` performs a deep evaluation or just hopes that random addition of `!` to some arguments may improve speed or memory consumption. This results in useless source clutter.
|
|
|
|
|
|
##### Algebraic Constructors
|
|
|
Always warn if we are pattern matching against Data Constructor - since the act of pattern matching evaluates the value to WHNF already.
|
|
|
|
|
|
However, do check if this is a newtype. If it is - don't warn but perform the check on its argument.
|
|
|
|
|
|
##### Lists
|
|
|
|
|
|
Always warn about bang unless `RebindableSyntax` is ON. In that case we don't know what is going on so do not bother.
|
|
|
|
|
|
##### Tuples
|
|
|
|
|
|
Always warn for tuples - lifted and unlifted.
|
|
|
|
|
|
##### "Strict Bindings"
|
|
|
A bang at the top level of a let or where binding makes the binding strict, regardless of the pattern. In that case we only warn if the value is unlifted, which means it is alw Numbays strict.
|
|
|
|
|
|
`-Wunbanged-strict-patterns` requires us to write banged, unlifted bindings sometimes. For example:
|
|
|
|
|
|
```
|
|
|
let !(I# x) = 5 in ...
|
|
|
```
|
|
|
|
|
|
That bang is required by `-Wunbanged-strict-patterns`. In that case we don't warn.
|
|
|
|
|
|
##### Numeric Patterns
|
|
|
Consider:
|
|
|
```
|
|
|
data One = One deriving Show
|
|
|
|
|
|
instance Eq One where
|
|
|
_ == _ = True -- NB: lazy
|
|
|
|
|
|
instance Num One where
|
|
|
_ + _ = One
|
|
|
_ - _ = One
|
|
|
_ * _ = One
|
|
|
abs _ = One
|
|
|
signum _ = One
|
|
|
fromInteger _ = One
|
|
|
negate _ = One
|
|
|
|
|
|
foo :: One -> One
|
|
|
foo 5 = One
|
|
|
|
|
|
```
|
|
|
Evaluating `foo undefined` yields `One`. Putting a bang on the `5` pattern causes `foo undefined` to throw an exception instead. Thus, we don't warn about bangs.
|
|
|
|
|
|
##### Variable Patterns
|
|
|
Only warn if the type of pattern-matched value is unlifted.
|
|
|
|
|
|
```
|
|
|
foo :: Int -> ()
|
|
|
foo !i = () -- should warn
|
|
|
|
|
|
bar :: Int# -> ()
|
|
|
bar !i = () -- no warning!
|
|
|
```
|
|
|
|
|
|
##### Wild-card Patterns
|
|
|
Similar to variable patterns, only warn in case of unlifted type.
|
|
|
|
|
|
##### Sum Patterns
|
|
|
Always warn (because ... ?)
|
|
|
|
|
|
##### Other cases when we never warn
|
|
|
We never warn for:
|
|
|
* Lazy patterns
|
|
|
* View Patterns
|
|
|
* Splice Patterns
|
|
|
* Numeric Patterns |
|
|
\ No newline at end of file |