Skip to content

Commit

Permalink
deploy: 230bfed
Browse files Browse the repository at this point in the history
  • Loading branch information
BinderDavid committed Oct 11, 2024
1 parent 47cfa37 commit 4e088ae
Show file tree
Hide file tree
Showing 12 changed files with 478 additions and 2 deletions.
2 changes: 1 addition & 1 deletion api/errors.json

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h2>Welcome</h2>
</p>

<p>
So far, 116 errors and warnings are documented here.
So far, 117 errors and warnings are documented here.
If you encounter a message that is not yet documented, please
<a href="https://github.com/haskellfoundation/error-message-index/issues">open an issue</a> or
<a href="https://github.com/haskellfoundation/error-message-index/pulls">submit a pull request with documentation</a>.
Expand Down Expand Up @@ -317,6 +317,13 @@ <h2>The Messages</h2>
<td>9.6.1</td>
</tr>

<tr>
<td class="nowrap">GHC-38520</td>
<td><a href="./messages/GHC-38520/">Redundant Bang Patterns</a></td>
<td>Used a bang pattern that has no effect</td>
<td>9.6.1</td>
</tr>

<tr>
<td class="nowrap">GHC-39999</td>
<td><a href="./messages/GHC-39999/">No instance arising</a></td>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module AlreadyDeconstructed where

doubleIfTrue :: (Int, Bool) -> Int
doubleIfTrue (x, y) | y = x * 2
doubleIfTrue x = fst x
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module AlreadyDeconstructed where

doubleIfTrue :: (Int, Bool) -> Int
doubleIfTrue (x, y) | y = x * 2
doubleIfTrue !x = fst x
40 changes: 40 additions & 0 deletions messages/GHC-38520/alreadyDeconstructed/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<h2 id="warning-message">Warning message</h2>
<pre><code>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
| ^</code></pre>
<h2 id="explanation">Explanation</h2>
<p>It is possible that a previous clause already forced the evaluation of an expression.
For example, <code>doubleIfTrue</code>’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.</p>

<pre class="filename">AlreadyDeconstructed.hs</pre>
<div class="example-container">
<div class="example">
<div class="example-inner">
<div class="example-title">Before</div>
<!-- keep next line as is, i.e., on one line, or the code will not format properly -->
<pre class="example-pre"><code class="language-haskell">module AlreadyDeconstructed where

doubleIfTrue :: (Int, Bool) -> Int
doubleIfTrue (x, y) | y = x * 2
doubleIfTrue !x = fst x
</code></pre>
</div>
</div>
<div class="example">
<div class="example-inner">
<div class="example-title">After</div>
<!-- keep next line as is, i.e., on one line, or the code will not format propertly -->
<pre class="example-pre"><code class="language-haskell">module AlreadyDeconstructed where

doubleIfTrue :: (Int, Bool) -> Int
doubleIfTrue (x, y) | y = x * 2
doubleIfTrue x = fst x
</code></pre>
</div>
</div>
</div>

251 changes: 251 additions & 0 deletions messages/GHC-38520/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Redundant Bang Patterns [GHC-38520] — Haskell Error Index</title>
<link rel="stylesheet" href="../../css/highlight.css">
<script src="../../js/highlight.min.js"></script>
<link rel="stylesheet" href="../../css/default.css" />
<link rel="stylesheet" href="../../css/theme.css" />
</head>

<body>
<main role="main">
<nav class="breadcrumb">

<a href="../../">The Haskell Error Index</a>&nbsp;»

Redundant Bang Patterns [GHC-38520]
</nav>
<h1>Redundant Bang Patterns [GHC-38520]</h1>

<p>
<i>Flag: <code>-Wredundant-bang-patterns</code></i><br />



</p>


<p>The <code>BangPatterns</code> 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.</p>
<p>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 <code>Int#</code> or <code>Array#</code>.</p>
<p>In all of these cases, the Bang Pattern has no added effect, so it is redundant.</p>



<h2>Examples</h2>

<details open="open">
<summary>Already deconstructed</summary>
<div class="details-inner">
<h2 id="warning-message">Warning message</h2>
<pre><code>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
| ^</code></pre>
<h2 id="explanation">Explanation</h2>
<p>It is possible that a previous clause already forced the evaluation of an expression.
For example, <code>doubleIfTrue</code>’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.</p>

<pre class="filename">AlreadyDeconstructed.hs</pre>
<div class="example-container">
<div class="example">
<div class="example-inner">
<div class="example-title">Before</div>
<!-- keep next line as is, i.e., on one line, or the code will not format properly -->
<pre class="example-pre"><code class="language-haskell">module AlreadyDeconstructed where

doubleIfTrue :: (Int, Bool) -> Int
doubleIfTrue (x, y) | y = x * 2
doubleIfTrue !x = fst x
</code></pre>
</div>
</div>
<div class="example">
<div class="example-inner">
<div class="example-title">After</div>
<!-- keep next line as is, i.e., on one line, or the code will not format propertly -->
<pre class="example-pre"><code class="language-haskell">module AlreadyDeconstructed where

doubleIfTrue :: (Int, Bool) -> Int
doubleIfTrue (x, y) | y = x * 2
doubleIfTrue x = fst x
</code></pre>
</div>
</div>
</div>


</div>
</details>

<details open="open">
<summary>Strict fields</summary>
<div class="details-inner">
<h2 id="warning-message">Warning message</h2>
<pre><code>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 = ()
| ^ </code></pre>
<h2 id="explanation">Explanation</h2>
<p>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.</p>

<pre class="filename">StrictField.hs</pre>
<div class="example-container">
<div class="example">
<div class="example-inner">
<div class="example-title">Before</div>
<!-- keep next line as is, i.e., on one line, or the code will not format properly -->
<pre class="example-pre"><code class="language-haskell">module StrictField where

data Foo = MkFoo !Int Int

foo :: Foo -> Foo -> ()
foo !a (MkFoo !b !c) = ()
</code></pre>
</div>
</div>
<div class="example">
<div class="example-inner">
<div class="example-title">After</div>
<!-- keep next line as is, i.e., on one line, or the code will not format propertly -->
<pre class="example-pre"><code class="language-haskell">module StrictField where

data Foo = MkFoo !Int Int

foo :: Foo -> Foo -> ()
foo !a (MkFoo b !c) = ()
</code></pre>
</div>
</div>
</div>


</div>
</details>

<details open="open">
<summary>Unlifted and unboxed types</summary>
<div class="details-inner">
<h2 id="warning-messages">Warning messages</h2>
<pre><code>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 = ()
| ^</code></pre>
<h2 id="explanation">Explanation</h2>
<p>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.</p>

<pre class="filename">UnliftedTypes.hs</pre>
<div class="example-container">
<div class="example">
<div class="example-inner">
<div class="example-title">Before</div>
<!-- keep next line as is, i.e., on one line, or the code will not format properly -->
<pre class="example-pre"><code class="language-haskell">{-# 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 = ()
</code></pre>
</div>
</div>
<div class="example">
<div class="example-inner">
<div class="example-title">After</div>
<!-- keep next line as is, i.e., on one line, or the code will not format propertly -->
<pre class="example-pre"><code class="language-haskell">{-# 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 = ()
</code></pre>
</div>
</div>
</div>


</div>
</details>



</main>

<footer>
<p class="HF foot">
This site is a project of <a href="https://haskell.foundation" target="_blank" rel="noopener noreferrer">The
Haskell Foundation</a>.
</p>
<p class="shoutout foot">
Site proudly generated by
<a href="http://jaspervdj.be/hakyll" target="_blank" rel="noopener noreferrer">Hakyll</a>
</p>
</footer>

<script>document.querySelectorAll('code.language-haskell').forEach(el => {
hljs.highlightElement(el);
});</script>
</body>

</html>
6 changes: 6 additions & 0 deletions messages/GHC-38520/strictField/after/StrictField.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module StrictField where

data Foo = MkFoo !Int Int

foo :: Foo -> Foo -> ()
foo !a (MkFoo b !c) = ()
6 changes: 6 additions & 0 deletions messages/GHC-38520/strictField/before/StrictField.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module StrictField where

data Foo = MkFoo !Int Int

foo :: Foo -> Foo -> ()
foo !a (MkFoo !b !c) = ()
44 changes: 44 additions & 0 deletions messages/GHC-38520/strictField/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<h2 id="warning-message">Warning message</h2>
<pre><code>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 = ()
| ^ </code></pre>
<h2 id="explanation">Explanation</h2>
<p>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.</p>

<pre class="filename">StrictField.hs</pre>
<div class="example-container">
<div class="example">
<div class="example-inner">
<div class="example-title">Before</div>
<!-- keep next line as is, i.e., on one line, or the code will not format properly -->
<pre class="example-pre"><code class="language-haskell">module StrictField where

data Foo = MkFoo !Int Int

foo :: Foo -> Foo -> ()
foo !a (MkFoo !b !c) = ()
</code></pre>
</div>
</div>
<div class="example">
<div class="example-inner">
<div class="example-title">After</div>
<!-- keep next line as is, i.e., on one line, or the code will not format propertly -->
<pre class="example-pre"><code class="language-haskell">module StrictField where

data Foo = MkFoo !Int Int

foo :: Foo -> Foo -> ()
foo !a (MkFoo b !c) = ()
</code></pre>
</div>
</div>
</div>

Loading

0 comments on commit 4e088ae

Please sign in to comment.