-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.
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.
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.
Always warn about bang unless
RebindableSyntax is ON. In that case we don't know what is going on so do not bother.
Always warn for tuples - lifted and unlifted.
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.
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
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.
Only warn if the type of pattern-matched value is unlifted.
foo :: Int -> () foo !i = () -- should warn bar :: Int# -> () bar !i = () -- no warning!
Similar to variable patterns, only warn in case of unlifted type.
Always warn (because ... ?)
Other cases when we never warn
We never warn for:
- Lazy patterns
- View Patterns
- Splice Patterns
- Numeric Patterns