From 230bfedeee8bddb9abbee1aabbe3fcea626038bd Mon Sep 17 00:00:00 2001 From: Adowrath Date: Fri, 11 Oct 2024 11:21:56 +0200 Subject: [PATCH] Add documentation for GHC-38520 (Redundant Bang Patterns) (#528) * Add documentation for GHC-38520 (Redundant Bang Patterns) Fixes #177 * Some slight editing --------- Co-authored-by: David Binder --- .../after/AlreadyDeconstructed.hs | 5 +++ .../before/AlreadyDeconstructed.hs | 5 +++ .../GHC-38520/alreadyDeconstructed/index.md | 20 +++++++++++ message-index/messages/GHC-38520/index.md | 20 +++++++++++ .../strictField/after/StrictField.hs | 6 ++++ .../strictField/before/StrictField.hs | 6 ++++ .../messages/GHC-38520/strictField/index.md | 22 ++++++++++++ .../unliftedTypes/after/UnliftedTypes.hs | 17 ++++++++++ .../unliftedTypes/before/UnliftedTypes.hs | 17 ++++++++++ .../messages/GHC-38520/unliftedTypes/index.md | 34 +++++++++++++++++++ 10 files changed, 152 insertions(+) create mode 100644 message-index/messages/GHC-38520/alreadyDeconstructed/after/AlreadyDeconstructed.hs create mode 100644 message-index/messages/GHC-38520/alreadyDeconstructed/before/AlreadyDeconstructed.hs create mode 100644 message-index/messages/GHC-38520/alreadyDeconstructed/index.md create mode 100644 message-index/messages/GHC-38520/index.md create mode 100644 message-index/messages/GHC-38520/strictField/after/StrictField.hs create mode 100644 message-index/messages/GHC-38520/strictField/before/StrictField.hs create mode 100644 message-index/messages/GHC-38520/strictField/index.md create mode 100644 message-index/messages/GHC-38520/unliftedTypes/after/UnliftedTypes.hs create mode 100644 message-index/messages/GHC-38520/unliftedTypes/before/UnliftedTypes.hs create mode 100644 message-index/messages/GHC-38520/unliftedTypes/index.md diff --git a/message-index/messages/GHC-38520/alreadyDeconstructed/after/AlreadyDeconstructed.hs b/message-index/messages/GHC-38520/alreadyDeconstructed/after/AlreadyDeconstructed.hs new file mode 100644 index 00000000..7d05b9a8 --- /dev/null +++ b/message-index/messages/GHC-38520/alreadyDeconstructed/after/AlreadyDeconstructed.hs @@ -0,0 +1,5 @@ +module AlreadyDeconstructed where + +doubleIfTrue :: (Int, Bool) -> Int +doubleIfTrue (x, y) | y = x * 2 +doubleIfTrue x = fst x diff --git a/message-index/messages/GHC-38520/alreadyDeconstructed/before/AlreadyDeconstructed.hs b/message-index/messages/GHC-38520/alreadyDeconstructed/before/AlreadyDeconstructed.hs new file mode 100644 index 00000000..f9c65041 --- /dev/null +++ b/message-index/messages/GHC-38520/alreadyDeconstructed/before/AlreadyDeconstructed.hs @@ -0,0 +1,5 @@ +module AlreadyDeconstructed where + +doubleIfTrue :: (Int, Bool) -> Int +doubleIfTrue (x, y) | y = x * 2 +doubleIfTrue !x = fst x diff --git a/message-index/messages/GHC-38520/alreadyDeconstructed/index.md b/message-index/messages/GHC-38520/alreadyDeconstructed/index.md new file mode 100644 index 00000000..47215893 --- /dev/null +++ b/message-index/messages/GHC-38520/alreadyDeconstructed/index.md @@ -0,0 +1,20 @@ +--- +title: Already deconstructed +--- + +## Warning message + +``` +AlreadyDeconstructed.hs:5:15: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘doubleIfTrue’: doubleIfTrue x = ... + | +5 | doubleIfTrue !x = fst x + | ^ +``` + +## Explanation + +It is possible that a previous clause already forced the evaluation of an expression. +For example, `doubleIfTrue`'s first clause already deconstructs the pair tuple, so +a bang pattern on the tuple as a whole has no effect in the second clause. diff --git a/message-index/messages/GHC-38520/index.md b/message-index/messages/GHC-38520/index.md new file mode 100644 index 00000000..e6675225 --- /dev/null +++ b/message-index/messages/GHC-38520/index.md @@ -0,0 +1,20 @@ +--- +title: Redundant Bang Patterns +summary: Used a bang pattern that has no effect +severity: warning +flag: -Wredundant-bang-patterns +introduced: 9.6.1 +--- + +The `BangPatterns` extension allows the user to mark parts of a pattern as strict by prefixing the pattern with an exclamation mark. +By default, Haskell only evaluates an expression as little as it needs to determine whether the pattern matches or not. +Using bang patterns causes the matched expression to always be evaluated to weak head normal +form (WHNF) before the rest of the clauses, any guard patterns, or the right-hand side +of the clause are executed. + +However, there are cases where a bang pattern can be redundant. +This happens either because a previous match clause already forced the evaluation, because the user is +trying to match on a strict field of a data type, or because the type of the value being +matched on is of an unlifted or unboxed type like `Int#` or `Array#`. + +In all of these cases, the Bang Pattern has no added effect, so it is redundant. diff --git a/message-index/messages/GHC-38520/strictField/after/StrictField.hs b/message-index/messages/GHC-38520/strictField/after/StrictField.hs new file mode 100644 index 00000000..16570143 --- /dev/null +++ b/message-index/messages/GHC-38520/strictField/after/StrictField.hs @@ -0,0 +1,6 @@ +module StrictField where + +data Foo = MkFoo !Int Int + +foo :: Foo -> Foo -> () +foo !a (MkFoo b !c) = () diff --git a/message-index/messages/GHC-38520/strictField/before/StrictField.hs b/message-index/messages/GHC-38520/strictField/before/StrictField.hs new file mode 100644 index 00000000..28cf9d27 --- /dev/null +++ b/message-index/messages/GHC-38520/strictField/before/StrictField.hs @@ -0,0 +1,6 @@ +module StrictField where + +data Foo = MkFoo !Int Int + +foo :: Foo -> Foo -> () +foo !a (MkFoo !b !c) = () diff --git a/message-index/messages/GHC-38520/strictField/index.md b/message-index/messages/GHC-38520/strictField/index.md new file mode 100644 index 00000000..5dde3738 --- /dev/null +++ b/message-index/messages/GHC-38520/strictField/index.md @@ -0,0 +1,22 @@ +--- +title: Strict fields +--- + +## Warning message + +``` +UnliftedTypes.hs:17:6: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘foo’: foo a = ... + | +17 | foo !a !b !c = () + | ^ +``` + +## Explanation + +Haskell allows a user to annotate fields of a datatype as strict, by prepending +their type with an exclamation mark. +Pattern matching on such a constructor forces it to WHNF, but this also automatically +forces any strict fields to evaluate to WHNF as well. +Thus, a Bang Pattern has no effect on a strict field. diff --git a/message-index/messages/GHC-38520/unliftedTypes/after/UnliftedTypes.hs b/message-index/messages/GHC-38520/unliftedTypes/after/UnliftedTypes.hs new file mode 100644 index 00000000..3ae83e4c --- /dev/null +++ b/message-index/messages/GHC-38520/unliftedTypes/after/UnliftedTypes.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE UnliftedNewtypes #-} + +module UnliftedTypes where + +import GHC.Exts + +newtype MyInt :: TYPE 'IntRep where + MkMyInt :: Int# -> MyInt + +foo :: Int# -> MyInt -> (# Int, Int #) -> () +foo a b c = () diff --git a/message-index/messages/GHC-38520/unliftedTypes/before/UnliftedTypes.hs b/message-index/messages/GHC-38520/unliftedTypes/before/UnliftedTypes.hs new file mode 100644 index 00000000..0d28a4cd --- /dev/null +++ b/message-index/messages/GHC-38520/unliftedTypes/before/UnliftedTypes.hs @@ -0,0 +1,17 @@ +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE KindSignatures #-} +{-# LANGUAGE UnboxedTuples #-} +{-# LANGUAGE UnliftedNewtypes #-} + +module UnliftedTypes where + +import GHC.Exts + +newtype MyInt :: TYPE 'IntRep where + MkMyInt :: Int# -> MyInt + +foo :: Int# -> MyInt -> (# Int, Int #) -> () +foo !a !b !c = () diff --git a/message-index/messages/GHC-38520/unliftedTypes/index.md b/message-index/messages/GHC-38520/unliftedTypes/index.md new file mode 100644 index 00000000..f1e560c3 --- /dev/null +++ b/message-index/messages/GHC-38520/unliftedTypes/index.md @@ -0,0 +1,34 @@ +--- +title: Unlifted and unboxed types +--- + +## Warning messages + +``` +UnliftedTypes.hs:17:6: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘foo’: foo a = ... + | +17 | foo !a !b !c = () + | ^ + +UnliftedTypes.hs:17:9: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘foo’: foo b = ... + | +17 | foo !a !b !c = () + | ^ + +UnliftedTypes.hs:17:12: warning: [-Wredundant-bang-patterns] + Pattern match has redundant bang + In an equation for ‘foo’: foo c = ... + | +17 | foo !a !b !c = () + | ^ +``` + +## Explanation + +Forcing the evaluation of a value up to WHNF does not make sense for unlifted and +unboxed types, because these types can never be represented by an unevaluated expression at runtime. +Thus, trying to enforce strictness via a bang pattern has no effect.