| CARVIEW |
Select Language
HTTP/2 200
cross-origin-resource-policy: cross-origin
etag: W/"36a5025a6034931b9c85b712fe92b1ac50aa8deef63a393fcf6f68b74d82cf26"
date: Sun, 18 Jan 2026 07:09:58 GMT
content-type: application/atom+xml; charset=UTF-8
server: blogger-renderd
expires: Sun, 18 Jan 2026 07:09:59 GMT
cache-control: public, must-revalidate, proxy-revalidate, max-age=1
x-content-type-options: nosniff
x-xss-protection: 0
last-modified: Wed, 28 Aug 2024 04:13:34 GMT
content-encoding: gzip
content-length: 13964
x-frame-options: SAMEORIGIN
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
tag:blogger.com,1999:blog-6608236561517658557 2024-08-28T04:13:34.709+00:00 Auke Booij's programming and logic Auke https://www.blogger.com/profile/12557099016349698408 noreply@blogger.com Blogger 5 1 25 tag:blogger.com,1999:blog-6608236561517658557.post-5903795569736392696 2021-02-09T18:51:00.000+00:00 2021-02-09T18:56:03.495+00:00 -XFunctorialDo <p>tl;dr: <code>ApplicativeDo</code> is useful also for functors. However, use laziness when pattern matching. The GHC manual remains a fantastic resource for learning about language extensions.</p>
<p>By default, <code>do</code> blocks are associated with <code>Monad</code> constraints. You might know that by enabling the <code>ApplicativeDo</code> language extension, we can write <code>do</code> blocks for unary type constructors that are not monads, but only applicatives. (Recall that <code>Monad</code> is a subclass of <code>Applicative</code> <a href="https://wiki.haskell.org/Functor-Applicative-Monad_Proposal">since GHC 7.10.1</a>.)<!--
> {- HLINT ignore "Use let" -}
> {- HLINT ignore "Redundant return" -}
> {- HLINT ignore "Redundant pure" -}
> {- HLINT ignore "Use <$>" -}
> {-# OPTIONS_GHC -fno-warn-unused-top-binds #-}
> {-# OPTIONS_GHC -fno-warn-unused-matches #-}
--></p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="ot">{-# LANGUAGE ApplicativeDo #-}</span></span></code></pre></div>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="ot">showAnInt ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> f <span class="dt">Int</span> <span class="ot">-></span> f <span class="dt">String</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>showAnInt action <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a> n <span class="ot"><-</span> action</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a> <span class="fu">return</span> <span class="op">$</span> <span class="fu">show</span> n</span></code></pre></div>
<p>But did you know that we can also write <code>do</code> blocks for <code>Functor</code>s?</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">-- Note the 'Functor' constraint rather than 'Applicative'.</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="ot">showAnIntFunctor ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> f <span class="dt">Int</span> <span class="ot">-></span> f <span class="dt">String</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a>showAnIntFunctor action <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a> n <span class="ot"><-</span> action</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a> <span class="fu">return</span> <span class="op">$</span> <span class="fu">show</span> n</span></code></pre></div>
<p>I encountered this accidentally while writing code for <a href="https://hasura.io/">Hasura</a>: I wrote a <code>do</code> block for something that I suspected might have an <code>Applicative</code> instance. It compiled, and everything was fine, but at a later stage I could not track down where that instance was defined.</p>
<h1 id="origins">Origins</h1>
<p>At first, I suspected that the GHC rewriting mechanism was kicking in just in time to compile (the equivalent of) <code>showAnIntFunctor</code> down to something like <code>(show <$>)</code>. In retrospect, this was a bad suspicion: it would be terribly confusing if the rewriting mechanism would arbitrarily change the type of things. Put differently, the motto should be: terms that are well-typed <em>with</em> rewriting should also be well-typed <em>without</em> rewriting.</p>
<p>So why does it work?</p>
<p>Certainly, <code>ApplicativeDo</code> does not simply relax the <code>Monad</code> constraint on <code>do</code> blocks to <code>Applicative</code>, since some <code>do</code> blocks cannot be desugared to code in terms of the <code>Applicative</code> methods. A very simple example of that is:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a>applyToPackage box action <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a> x <span class="ot"><-</span> box</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a> action x</span></code></pre></div>
<p>The above doesn’t work for <code>Applicative</code>s, because it implements exactly the <code>(>>=)</code> operator that distinguishes <code>Monad</code>s from <code>Applicative</code>s. Hence:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">-- Note the 'Monad' constraint despite us having switched on 'ApplicativeDo'</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="ot">applyToPackage ::</span> <span class="dt">Monad</span> f <span class="ot">=></span> f a <span class="ot">-></span> (a <span class="ot">-></span> f b) <span class="ot">-></span> f b</span></code></pre></div>
<p>So how does the appropriate constraint on a given <code>do</code> block arise? The constraint is not generated directly by GHC. Rather, normally, a <code>do</code> block is desugared into applications of <code>(>>=)</code>, and it is through these operators that a <code>Monad</code> constraint normally arises. In fact, already without <code>ApplicativeDo</code>, the following compiles:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co">-- NB: No constraints on 'f' are required.</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="ot">justDoIt ::</span> f <span class="dt">Int</span> <span class="ot">-></span> f <span class="dt">Int</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a>justDoIt action <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a> action</span></code></pre></div>
<p>The logic that <code>ApplicativeDo</code> adds is that it does a syntactic analysis of the code inside the <code>do</code> block, in order to make use of <code>(<$>)</code> and <code>(<*>)</code> rather than <code>(>>=)</code> where possible.</p>
<p>This syntactic analysis works out to a single application of <code>(<$>)</code> for the above example of <code>showAnIntFunctor</code>. But this analysis is imperfect and does not always produce the expected result. For instance, all of the following four methods can be “desugared” to <code>pure :: Applicative f => a -> f a</code>:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a>pure1 <span class="ot">=</span> <span class="fu">return</span></span></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a>pure2 x <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a> <span class="fu">return</span> x</span></code></pre></div>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a>pure3 x <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a> y <span class="ot"><-</span> <span class="fu">pure</span> x</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a> <span class="fu">return</span> x</span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a>pure4 x <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a> y <span class="ot"><-</span> <span class="fu">return</span> x</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a> <span class="fu">return</span> x</span></code></pre></div>
<p>However, only the third item is considered to be <code>Applicative</code> by the <code>ApplicativeDo</code> extension.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="ot">pure1 ::</span> <span class="dt">Monad</span> f <span class="ot">=></span> a <span class="ot">-></span> f a</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="ot">pure2 ::</span> <span class="dt">Monad</span> f <span class="ot">=></span> a <span class="ot">-></span> f a</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a><span class="ot">pure3 ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> a <span class="ot">-></span> f a</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a><span class="ot">pure4 ::</span> <span class="dt">Monad</span> f <span class="ot">=></span> a <span class="ot">-></span> f a</span></code></pre></div>
<p>Perhaps, if <code>return</code> becomes an alias for <code>pure</code>, i.e. after the <a href="https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/monad-of-no-return">monad of no return</a> GHC proposal is implemented, all four can be generalized to <code>Applicative</code>.</p>
<p>Similarly, one can write convoluted <code>do</code> blocks that can be implemented by <code>id :: f a -> f a</code>, which requires no constraints on <code>f</code>, but regardless <code>ApplicativeDo</code> desugars those <code>do</code> blocks to code that has constraints on <code>f</code>.</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a>constrainedId xM <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a> x <span class="ot"><-</span> xM</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a> <span class="fu">pure</span> x</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a><span class="ot">constrainedId ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> f a <span class="ot">-></span> f a</span></code></pre></div>
<h1 id="pattern-matching">Pattern matching</h1>
<p>One further oddity arises when pattern matching. Perhaps surprisingly, the code</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a>unpackAndApply1 gM xyF <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true"></a> (i, _) <span class="ot"><-</span> xyF</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a> g <span class="ot"><-</span> gM</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a> <span class="fu">return</span> <span class="op">$</span> g i</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true"></a><span class="ot">unpackAndApply1 ::</span> <span class="dt">Monad</span> f <span class="ot">=></span> f (<span class="dt">Int</span> <span class="ot">-></span> a) <span class="ot">-></span> f (<span class="dt">Int</span>, <span class="dt">String</span>) <span class="ot">-></span> f a</span></code></pre></div>
<p>gets a <code>Monad</code> constraint, despite the code seemingly only requiring <code>Applicative</code>: just capture the result of the monadic action and unpack it with <code>fst</code>, avoiding <code>(>>=)</code>.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true"></a>unpackAndApply2 gM xyF <span class="ot">=</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true"></a> gM <span class="op"><*></span> (<span class="fu">fst</span> <span class="op"><$></span> xyF)</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true"></a><span class="ot">unpackAndApply2 ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> f (<span class="dt">Int</span> <span class="ot">-></span> a) <span class="ot">-></span> f (<span class="dt">Int</span>, <span class="dt">String</span>) <span class="ot">-></span> f a</span></code></pre></div>
<p>So why the <code>Monad</code> constraint? Again I originally started with an incorrect suspicion, namely that this was because the pattern match might fail (think of a <code>Left</code> pattern match on an <code>Either</code> value), and was hence injecting a call to <code>fail</code>. But, in retrospect, that doesn’t make sense, since the constraint is <code>Monad f</code>, not <code>MonadFail f</code>. Born in the wrong generation, I guess…</p>
<p>The answer is that there’s a semantic difference between</p>
<ul>
<li><code>unpackAndApply1 (const 'a') (pure undefined)</code> (which is <code>undefined</code>) and</li>
<li><code>unpackAndApply2 (const 'a') (pure undefined)</code> (which is <code>pure 'a'</code>).</li>
</ul>
<p>Hence, <code>ApplicativeDo</code> does not desuger <code>unpackAndApply1</code> into <code>unpackAndApply2</code> since it would change the strictness of the <code>do</code> block.</p>
<p>We can convince <code>ApplicativeDo</code> otherwise by flagging the pattern match as being lazy:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true"></a>unpackAndApply3 gM xyF <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true"></a> <span class="op">~</span>(i, _) <span class="ot"><-</span> xyF</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true"></a> g <span class="ot"><-</span> gM</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true"></a> <span class="fu">return</span> <span class="op">$</span> g i</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true"></a><span class="ot">unpackAndApply3 ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> f (<span class="dt">Int</span> <span class="ot">-></span> a) <span class="ot">-></span> f (<span class="dt">Int</span>, <span class="dt">String</span>) <span class="ot">-></span> f a</span></code></pre></div>
<p>This moves the goalpost by allowing the tuple to be unpacked on an as-needed basis.</p>
<p>Another way to resolve it is by manually moving the pattern match to a point where it doesn’t interfere with an applicative desugaring of the <code>do</code> block:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true"></a>unpackAndApply4 gM xyF <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true"></a> x'y <span class="ot"><-</span> xyF</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true"></a> g <span class="ot"><-</span> gM</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true"></a> <span class="fu">return</span> <span class="op">$</span> g (<span class="fu">fst</span> x'y) <span class="co">-- now the unpacking happens here</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a><span class="ot">unpackAndApply4 ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> f (<span class="dt">Int</span> <span class="ot">-></span> a) <span class="ot">-></span> f (<span class="dt">Int</span>, <span class="dt">String</span>) <span class="ot">-></span> f a</span></code></pre></div>
<p><code>unpackAndApply2</code>, <code>unpackAndApply3</code> and <code>unpackAndApply4</code> should be semantically equal.</p>
<h1 id="parallelism">Parallelism</h1>
<p>The <a href="https://www.microsoft.com/en-us/research/publication/desugaring-haskells-do-notation-into-applicative-operations/">original motivation</a> for <code>ApplicativeDo</code> was to speed up certain code written in <code>do</code> blocks, even when a <code>Monad</code> instance is in scope. The idea was that <code>(<$>)</code> and <code>(<*>)</code> allowed for more efficient implementations than the default ones arising from <code>(>>=)</code> and <code>return</code>. The final desugaring of a <code>do</code> block might be a mixture of all of <code>(<$>)</code>, <code>(<*>)</code> and <code>(>>=)</code>, where parts of the applicative-based may be executed “in parallel”, and parts which are necessarily monadic are executed “sequentially”, whatever those two terms mean in the domain of the code.</p>
<p>In order to make optimal use of this, it is important to organize <code>do</code> blocks in such a way that the functorial and applicative operators can kick in. For instance, the first block can be optimized better than the second block: (this example comes straight from the paper linked above) (both require a <code>Monad</code>)</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true"></a>variant1 xM xM' f f' <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true"></a> x <span class="ot"><-</span> xM</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true"></a> y <span class="ot"><-</span> f x</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true"></a> x' <span class="ot"><-</span> xM'</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true"></a> y' <span class="ot"><-</span> f' x'</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true"></a> <span class="fu">return</span> (y, y')</span></code></pre></div>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true"></a>variant2 xM xM' f f' <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true"></a> x <span class="ot"><-</span> xM</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true"></a> x' <span class="ot"><-</span> xM' <span class="co">-- note this line being executed earlier,</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true"></a> y <span class="ot"><-</span> f x <span class="co">-- ... before the call to 'f'</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true"></a> y' <span class="ot"><-</span> f' x'</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true"></a> <span class="fu">return</span> (y, y')</span></code></pre></div>
<p>The problem is that the call to <code>xM'</code> in the second variant prevents <code>f</code> from starting execution, whereas in the first version the computation of <code>y</code> and <code>y'</code> are fully independent. Algebraically, we can say that <code>ApplicativeDo</code> only applies those transformations that follow the laws of functors/applicatives/monads, and reordering monadic actions is not allowed in general (and in fact, not well-typed in general).</p>
<p>So when writing monadic code that can potentially be desugared into more efficient code using applicative combinators (even partially), the motto to keep in mind is “related things go together”.</p>
<p>This is somewhat opposed to low-level machine code, where one tries to <em>maximize</em> the number of instructions between, for instance, fetching data from memory and using that data, so that high-performance processor architectures such as pipelining and out-of-order-execution work optimally.</p>
<h1 id="ghc-users-guide">GHC User’s Guide</h1>
<p>I haven’t said anything fundamentally new in this blog post. Most of this content can also be found in the <a href="https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/applicative_do.html">GHC User’s Guide</a>, and indeed that was my main source. I found the documentation there very readable, and it answered exactly the questions that I found myself asking.<!--
> variant1
> :: Monad f
> => f Int
> -> f Char
> -> (Int -> f a)
> -> (Char -> f b)
> -> f (a, b)
> variant2
> :: Monad f
> => f Int
> -> f Char
> -> (Int -> f a)
> -> (Char -> f b)
> -> f (a, b)
> main :: IO ()
> main = print "hello"
--></p>
Auke https://www.blogger.com/profile/12557099016349698408 noreply@blogger.com 0 tag:blogger.com,1999:blog-6608236561517658557.post-7224335669938264084 2020-08-31T18:52:00.000+00:00 2020-08-31T18:52:40.388+00:00 Property testing property testers <details>
<summary>
Show the Haskell imports
</summary>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="kw">import</span> <span class="dt">Numeric.Natural</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="kw">import</span> <span class="dt">Data.Maybe</span></span></code></pre></div>
</details>
<p>Property testers such as QuickCheck are used to search for inputs that invalidate a given property. We focus on properties that are implemented in Haskell as a function <code>a -> Bool</code>. In the context of QuickCheck, the type <code>a</code> is assumed to be an instance of the <code>Arbitrary</code> type class, allowing to randomly generate values of <code>a</code>. Because of its random nature, QuickCheck might not find any offending element of <code>a</code> even if it exists.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="kw">type</span> <span class="dt">Property</span> a <span class="ot">=</span> a <span class="ot">-></span> <span class="dt">Bool</span></span></code></pre></div>
<p>If the property tester managed to invalidate the property, it returns the offending element of <code>a</code>. Otherwise, it simply succeeds.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="kw">data</span> <span class="dt">Result</span> counterexample</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a> <span class="ot">=</span> <span class="dt">Success</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a> <span class="op">|</span> <span class="dt">Failure</span> counterexample</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="kw">instance</span> <span class="dt">Show</span> (<span class="dt">Result</span> counterexample) <span class="kw">where</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a> <span class="fu">show</span> <span class="dt">Success</span> <span class="ot">=</span> <span class="st">"Success"</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a> <span class="fu">show</span> (<span class="dt">Failure</span> _) <span class="ot">=</span> <span class="st">"Failure"</span></span></code></pre></div>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="kw">type</span> <span class="dt">Tester</span> a <span class="ot">=</span> <span class="dt">Property</span> a <span class="ot">-></span> <span class="dt">Result</span> a</span></code></pre></div>
<p>It is quite well-known in the functional programming community that there exist infinite <em>exhaustively testable</em> types. That is, in finite time we can exhaustively test whether a given property holds for all input values of type <code>a</code>, even, in some cases, when <code>a</code> is infinite.</p>
<p>A prototypical infinite exhaustively testable type, and the one we’ll focus on in this blog post, is the <em>Cantor space</em> of functions from the natural numbers to the Booleans.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="kw">type</span> <span class="dt">Cantor</span> <span class="ot">=</span> <span class="dt">Natural</span> <span class="ot">-></span> <span class="dt">Bool</span></span></code></pre></div>
<p>Expanding the above definition, exhaustive testability of Cantor space means that we can write a testing process of type <code>Tester Cantor = Property Cantor -> Result Cantor</code> that, for any property on Cantor space, succeeds when the property holds for all values of type <code>Cantor</code>, and returns a counterexample when there is a value of type <code>Cantor</code> for which it fails.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="ot">(#) ::</span> <span class="dt">Bool</span> <span class="ot">-></span> <span class="dt">Cantor</span> <span class="ot">-></span> <span class="dt">Cantor</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a>b <span class="op">#</span> f <span class="ot">=</span> \i <span class="ot">-></span> <span class="kw">if</span> i <span class="op">==</span> <span class="dv">0</span> <span class="kw">then</span> b <span class="kw">else</span> f (i<span class="op">-</span><span class="dv">1</span>)</span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co">-- Try to find a probe that invalidates the property.</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="ot">find ::</span> <span class="dt">Property</span> <span class="dt">Cantor</span> <span class="ot">-></span> <span class="dt">Cantor</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a>find prop <span class="ot">=</span> h <span class="op">#</span> find (\a <span class="ot">-></span> prop (h <span class="op">#</span> a))</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a> <span class="kw">where</span> h <span class="ot">=</span> prop (<span class="dt">False</span> <span class="op">#</span> find (\a <span class="ot">-></span> prop (<span class="dt">False</span> <span class="op">#</span> a)))</span></code></pre></div>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co">-- Exhaustively test a property on Cantor space</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="ot">exhaustiveCheck ::</span> <span class="dt">Tester</span> <span class="dt">Cantor</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a>exhaustiveCheck prop <span class="ot">=</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a> <span class="kw">if</span> prop probe</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a> <span class="co">-- The property holds on all inputs</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a> <span class="kw">then</span> <span class="dt">Success</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a> <span class="co">-- The property fails; 'probe' is a counterexample</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a> <span class="kw">else</span> <span class="dt">Failure</span> probe</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a> <span class="kw">where</span> probe <span class="ot">=</span> find prop</span></code></pre></div>
<p>The above fact has seen little application outside of papers and blog posts. This text, being a blog post, is no different. The raison d’être of this post is merely to, once again, observe this surprising fact, and to do something fun with it, as appears <a href="https://math.andrej.com/2007/09/28/seemingly-impossible-functional-programs/">to</a> <a href="https://math.andrej.com/2008/11/21/a-haskell-monad-for-infinite-search-in-finite-time/">be</a> <a href="https://lukepalmer.wordpress.com/2008/12/07/compact-data-types/">done</a> <a href="https://lukepalmer.wordpress.com/2010/11/17/searchable-data-types/">every</a> <a href="https://math.andrej.com/2011/12/06/how-to-make-the-impossible-functionals-run-even-faster/">couple</a> <a href="https://math.andrej.com/2014/05/08/seemingly-impossible-proofs/">of</a> <a href="https://julesh.com/2016/09/22/abusing-the-continuation-monad/">years</a>.</p>
<p>So what might we do with an exhaustive testing process <code>Property Cantor -> Result Cantor</code>? What property of Cantor space might we wish to exhaustively test? Such a property might test input-output behavior of a function that takes elements of Cantor space as input (though not necessarily returning Booleans). However, when we are thinking of QuickCheck-able programs, we normally think of types that are isomorphic to the natural numbers, such as strings and binary trees. “Oh, but that type is isomorphic to Cantor space!” is not the one-liner it could be among Haskellers.</p>
<p>Here’s the key observation of this blog post: <code>Cantor = Property Natural</code>.</p>
<p>So here’s a proposal for program we might want to phrase properties about: the QuickCheck-style property tester itself. After all, we may see a property tester for natural numbers as a map <code>Cantor -> Result Natural</code>, that takes a property of natural numbers (e.g. whether taking the square of a natural always results in an even number) and tells us whether it managed to find any inputs for which the property returns <code>False</code> (in this case, one might hope so).</p>
<p>Here are some sample implementations of property testers for us to play around with, which have some intentional shortcomings.</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co">-- A property tester that doesn't check the property against any</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a><span class="co">-- inputs and simply always succeeds</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a><span class="ot">testNothing ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span></span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a><span class="co">-- A property tester that only tests the input 0</span></span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a><span class="ot">testZero ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span></span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a><span class="co">-- A property tester that tests the property on inputs 0 through 100</span></span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a><span class="ot">test100 ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span></span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a><span class="co">-- A property tester that tests the property on inputs 100 through 200</span></span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a><span class="ot">testNext100 ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span></span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a><span class="co">-- A property tester that reports an incorrect witness of failure</span></span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a><span class="ot">testWrongWitness ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span></span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a><span class="co">-- A property tester that sometimes reports an incorrect witness:</span></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a><span class="co">-- only when the property holds for [0..100] and 100000,</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a><span class="co">-- but fails at 12345 and 26535</span></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a><span class="ot">testWrongWitnessSubtle ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span></span></code></pre></div>
<details>
<summary>
Show the implementations of these testers
</summary>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a>testNothing _ <span class="ot">=</span> <span class="dt">Success</span></span></code></pre></div>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a>testZero prop <span class="ot">=</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a> <span class="kw">if</span> prop <span class="dv">0</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a> <span class="kw">then</span> <span class="dt">Success</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a> <span class="kw">else</span> <span class="dt">Failure</span> <span class="dv">0</span></span></code></pre></div>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a>test100 prop <span class="ot">=</span> <span class="kw">case</span> tests <span class="kw">of</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a> [] <span class="ot">-></span> <span class="dt">Success</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a> i<span class="op">:</span>_ <span class="ot">-></span> <span class="dt">Failure</span> i</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a> <span class="kw">where</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a> tests <span class="ot">=</span> mapMaybe (\i <span class="ot">-></span> <span class="kw">if</span> prop i <span class="kw">then</span> <span class="dt">Nothing</span> <span class="kw">else</span> <span class="dt">Just</span> i) [<span class="dv">0</span><span class="op">..</span><span class="dv">100</span>]</span></code></pre></div>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true"></a>testNext100 prop <span class="ot">=</span> <span class="kw">case</span> tests <span class="kw">of</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true"></a> [] <span class="ot">-></span> <span class="dt">Success</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true"></a> i<span class="op">:</span>_ <span class="ot">-></span> <span class="dt">Failure</span> i</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true"></a> <span class="kw">where</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true"></a> tests <span class="ot">=</span> mapMaybe (\i <span class="ot">-></span> <span class="kw">if</span> prop i <span class="kw">then</span> <span class="dt">Nothing</span> <span class="kw">else</span> <span class="dt">Just</span> i) [<span class="dv">100</span><span class="op">..</span><span class="dv">200</span>]</span></code></pre></div>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true"></a>testWrongWitness prop <span class="ot">=</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true"></a> <span class="kw">if</span> prop <span class="dv">12345</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true"></a> <span class="kw">then</span> <span class="dt">Success</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true"></a> <span class="kw">else</span> <span class="dt">Failure</span> <span class="dv">9876</span></span></code></pre></div>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true"></a>testWrongWitnessSubtle prop <span class="ot">=</span> <span class="kw">case</span> test100 prop <span class="kw">of</span></span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true"></a> <span class="dt">Success</span> <span class="ot">-></span></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true"></a> <span class="kw">if</span> prop <span class="dv">100000</span></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true"></a> <span class="kw">then</span> <span class="kw">case</span> (prop <span class="dv">26535</span>, prop <span class="dv">12345</span>) <span class="kw">of</span></span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true"></a> (<span class="dt">True</span>, <span class="dt">True</span>) <span class="ot">-></span> <span class="dt">Success</span></span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true"></a> (<span class="dt">False</span>, <span class="dt">True</span>) <span class="ot">-></span> <span class="dt">Failure</span> <span class="dv">26535</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true"></a> (<span class="dt">True</span>, <span class="dt">False</span>) <span class="ot">-></span> <span class="dt">Failure</span> <span class="dv">12345</span></span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true"></a> (<span class="dt">False</span>, <span class="dt">False</span>) <span class="ot">-></span> <span class="dt">Failure</span> <span class="dv">9876</span> <span class="co">-- Wrong witness!</span></span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true"></a> <span class="kw">else</span> <span class="dt">Failure</span> <span class="dv">100000</span></span>
<span id="cb15-10"><a href="#cb15-10" aria-hidden="true"></a> <span class="dt">Failure</span> i <span class="ot">-></span> <span class="dt">Failure</span> i</span></code></pre></div>
</details>
<p>So what property can we phrase for a given property tester to satisfy? We can require that the property tester always tests the property at input 0. More precisely, if the property passes testing, then the property itself needs to hold at 0. We would expect <code>testNothing</code> to fail this test, but <code>testZero</code> and <code>test100</code> to satisfy it.</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true"></a><span class="ot">prop_alwaysTestZero ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span> <span class="ot">-></span> <span class="dt">Property</span> (<span class="dt">Property</span> <span class="dt">Natural</span>)</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true"></a>prop_alwaysTestZero tester prop <span class="ot">=</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true"></a> <span class="kw">case</span> tester prop <span class="kw">of</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true"></a> <span class="dt">Success</span> <span class="ot">-></span> prop <span class="dv">0</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true"></a> <span class="dt">Failure</span> _ <span class="ot">-></span> <span class="dt">True</span></span></code></pre></div>
<p>Note that we can’t directly check whether the property tester actually evaluated the property at 0: we only observe input-output behavior of the property tester. So in the case of a test failure, we can’t say anything about the required behavior of the property tester, since it might still fail because the property is false at another input. However, this is not reducing the power of our test at all, since we’re exhaustively testing over <em>all</em> properties of the naturals.</p>
<p>Just to drive this point home: for a given property tester <code>tester</code>, the property <code>prop_alwaysTestZero tester</code> isn’t just QuickCheck-able, in the sense that we can generate 100 inputs and see whether the property holds for those 100 inputs. It is <em>exhaustively</em> checkable, despite it stating a property of an infinite space. If the exhaustive check succeeds, we know that <code>prop_alwaysTestZero tester</code> holds for all properties on the naturals.</p>
<p>At this point, it is important to realize that, in the context of property testing, <em>properties</em> must in fact be <em>decidable</em>, rather than being arbitrary formulae in first-order logic (say). This restricts what we can test. In particular, we can’t test the claim “if the property always holds, then the property tester always succeeds”: because it is not decidable whether the input property always holds, so this claim itself is not a decidable property. But, since if the property tester fails, it also outputs a witness of this, we <em>can</em> test the contrapositive. So here is an exhaustively testable property expressing that if a property <em>fails</em> the property tester, then the witness provided by the property tester is actually an input for which the property is <code>False</code>. We would expect <code>testNothing</code>, <code>testZero</code> and <code>test100</code> to satisfy it, but <code>testWrongWitness</code> and <code>testWrongWitnessSubtle</code> to fail it.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true"></a><span class="ot">prop_failureActuallyFails ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span> <span class="ot">-></span> <span class="dt">Property</span> (<span class="dt">Property</span> <span class="dt">Natural</span>)</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true"></a>prop_failureActuallyFails tester prop <span class="ot">=</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true"></a> <span class="kw">case</span> tester prop <span class="kw">of</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true"></a> <span class="dt">Success</span> <span class="ot">-></span> <span class="dt">True</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true"></a> <span class="co">-- The property tester found a counterexample, so that better be one</span></span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true"></a> <span class="dt">Failure</span> n <span class="ot">-></span> <span class="fu">not</span> (prop n)</span></code></pre></div>
<p>This, I think, is a key property of property testers that is currently untested for QuickCheck. To be clear, I would expect QuickCheck to satisfy it, but strictly speaking it’s essential behavior that ought to be in the test suite.</p>
<p>QuickCheck attempts to <em>shrinks</em> counterexamples: so once it has randomly encountered a counterexample, it tries to find another which is intended to be smaller or simpler, in a sense specified by the implementation of <code>shrink</code> as part of the <code>Arbitrary</code> type class. We might therefore expect that if a tester finds a counterexample, that it picks a minimal one, in the sense that applying <code>shrink</code> to it does not yield any counterexamples that are smaller. For the natural numbers, this means that when we obtain a <code>Failure i</code>, then any natural smaller than <code>i</code> should <em>not</em> be a counterexample.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true"></a><span class="ot">prop_failureMinimal ::</span> <span class="dt">Tester</span> <span class="dt">Natural</span> <span class="ot">-></span> <span class="dt">Property</span> (<span class="dt">Property</span> <span class="dt">Natural</span>)</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true"></a>prop_failureMinimal tester prop <span class="ot">=</span></span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true"></a> <span class="kw">case</span> tester prop <span class="kw">of</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true"></a> <span class="dt">Success</span> <span class="ot">-></span> <span class="dt">True</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true"></a> <span class="dt">Failure</span> i <span class="ot">-></span> <span class="fu">all</span> prop (<span class="fu">init</span> [<span class="dv">0</span><span class="op">..</span>i])</span></code></pre></div>
<p>Here’s how we can run the exhaustive testing:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell literate"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true"></a><span class="ot">main ::</span> <span class="dt">IO</span> ()</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true"></a>main <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true"></a> <span class="fu">putStr</span> <span class="st">"Testing whether testNothing tests 0 (expecting Failure): "</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true"></a> <span class="fu">print</span> <span class="op">$</span> exhaustiveCheck (prop_alwaysTestZero testNothing)</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true"></a> <span class="fu">putStr</span> <span class="st">"Testing whether testZero tests 0 (expecting Success): "</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true"></a> <span class="fu">print</span> <span class="op">$</span> exhaustiveCheck (prop_alwaysTestZero testZero)</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true"></a> <span class="fu">putStr</span> <span class="st">"Testing whether test100 tests 0 (expecting Success): "</span></span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true"></a> <span class="fu">print</span> <span class="op">$</span> exhaustiveCheck (prop_alwaysTestZero test100)</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true"></a> <span class="fu">putStr</span> <span class="st">"Testing whether test100 yields minimal failure witnesses (expecting Success): "</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true"></a> <span class="fu">print</span> <span class="op">$</span> exhaustiveCheck (prop_failureMinimal test100)</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true"></a> <span class="fu">putStr</span> <span class="st">"Testing whether testNext100 yields minimal failure witnesses (expecting Failure): "</span></span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true"></a> <span class="fu">print</span> <span class="op">$</span> exhaustiveCheck (prop_failureMinimal testNext100)</span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true"></a> <span class="fu">putStr</span> <span class="st">"Testing whether test100 gives valid failure witnesses (expecting Success): "</span></span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true"></a> <span class="fu">print</span> <span class="op">$</span> exhaustiveCheck (prop_failureActuallyFails test100)</span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true"></a> <span class="fu">putStr</span> <span class="st">"Testing whether testWrongWitness gives valid failure witnesses (expecting Failure): "</span></span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true"></a> <span class="fu">print</span> <span class="op">$</span> exhaustiveCheck (prop_failureActuallyFails testWrongWitness)</span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true"></a> <span class="fu">putStr</span> <span class="st">"Testing whether testWrongWitnessSubtle gives valid failure witnesses (expecting Failure): "</span></span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true"></a> <span class="fu">print</span> <span class="op">$</span> exhaustiveCheck (prop_failureActuallyFails testWrongWitnessSubtle)</span></code></pre></div>
<p>I think the last test case best demonstrates the power of this approach. Normal <code>Arbitrary</code>-based property testing has no chance to catch the subtle bug in the implementation of the property tester <code>testWrongWitnessSubtle</code>. It would take deep inspection of the code of <code>testWrongWitnessSubtle</code> to write a counterexample manually. But this exhaustive technique finds a counterexample within 0.3 seconds on my machine, without any static analysis.</p>
<p>So why is this just a blog post rather than a pull request?</p>
<p>In reality, QuickCheck uses the IO monad to print additional information to the terminal, and to generate randomness, so that in this instance the true type of <code>quickCheck</code> would be closer to <code>(Natural -> Bool) -> IO (Result Natural)</code>. But we may imagine a pure variant of QuickCheck whose random number generator can be pre-seeded, and which computes a result purely without writing anything to the terminal. I’m not sure the above idea is adequate motivation to refactor QuickCheck in such a fundamental way. But, if anybody wants to work on this, do let me know.</p>
<p>Good luck to the next person writing a blog post about infinite searchable types!</p> Auke https://www.blogger.com/profile/12557099016349698408 noreply@blogger.com 0 tag:blogger.com,1999:blog-6608236561517658557.post-162397507360053806 2020-06-22T08:00:00.001+00:00 2020-07-22T13:21:21.598+00:00 Extensional constructive real analysis via locators <div>This is an announcement of a paper in the areas of constructive mathematics, (univalent) type theory, and exact real arithmetic.<br /></div><div><br /></div><div>Abstract: Real numbers do not admit an extensional procedure for observing discrete
information, such as the first digit of its decimal expansion, because every
extensional, computable map from the reals to the integers is constant, as is
well known. We overcome this by considering real numbers equipped with
additional structure, which we call a locator. With this structure, it is
possible, for instance, to construct a signed-digit representation or a Cauchy
sequence, and conversely these intensional representations give rise to a
locator. Although the constructions are reminiscent of computable analysis,
instead of working with a notion of computability, we simply work
constructively to extract observable information, and instead of working with
representations, we consider a certain locatedness structure on real numbers. <br /></div><div><br /></div><div>To appear in the MSCS <a href="https://hott-uf.github.io/special-issue-17-18/">Special Issue on Homotopy Type Theory and Univalent Foundations</a> (<a href="https://export.arxiv.org/abs/1805.06781">preprint on the arXiv</a>). This work is also discussed in some more generality in my <a href="https://abooij.blogspot.com/p/phd-thesis.html">PhD thesis</a>.<br /></div> Auke https://www.blogger.com/profile/12557099016349698408 noreply@blogger.com 2 tag:blogger.com,1999:blog-6608236561517658557.post-8493021457706321176 2017-06-20T08:00:00.003+00:00 2020-07-22T13:21:59.479+00:00 The HoTT book reals coincide with the Escardó-Simpson reals <p>This is an announcement of a paper in the area of univalent type theory and exact real arithmetic.</p><p>Escardó and Simpson defined a notion of interval object by a
universal property in any category with binary products. The Homotopy
Type Theory book defines a higher-inductive notion of reals, and
suggests that the interval may satisfy this universal property. We show
that this is indeed the case in the category of sets of any universe. We
also show that the type of HoTT book reals is the least Cauchy complete
subset of the Dedekind reals containing the rationals.<br /></p><p>Preprint is on the <a href="https://arxiv.org/abs/1706.05956">arXiv</a>.</p><p>Somewhat stronger results can be found in Chapter 5 of my <a href="https://abooij.blogspot.com/p/phd-thesis.html">PhD thesis</a>. I intend to publish these results at a later stage.<br /></p> Auke https://www.blogger.com/profile/12557099016349698408 noreply@blogger.com 0 tag:blogger.com,1999:blog-6608236561517658557.post-1194025478178391838 2016-12-01T09:00:00.001+00:00 2020-07-22T13:21:19.674+00:00 Parametricity, automorphisms of the universe, and excluded middle <div>This is an announcement of a paper in the area of type theory and parametricity.<br /></div><div><br /></div><div>Specific violations of parametricity, or existence of non-identity
automorphisms of the universe, can be used to prove classical axioms.
The former was <a href="https://homotopytypetheory.org/2016/02/24/parametricity-and-excluded-middle/">previously featured</a> on the Homotopy Type Theory blog, and the latter is part of <a href="https://groups.google.com/forum/#!searchin/homotopytypetheory/automorphisms|sort:relevance/homotopytypetheory/8CV0S2DuOI8/0XibNKHou1EJ">a discussion on the HoTT mailing list</a>.
In a cooperation between Martín Escardó, Peter Lumsdaine, Mike Shulman,
and myself, we have strengthened these results and recorded them in a
<a href="https://doi.org/10.4230/LIPIcs.TYPES.2016.7">paper that is published in the post-proceedings of TYPES 2016</a> (see also the <a href="https://arxiv.org/abs/1701.05617">preprint on arXiv</a>).</div> Auke https://www.blogger.com/profile/12557099016349698408 noreply@blogger.com 0