<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Austin Rochford (Posts about Testing)</title><link>https://austinrochford.com/</link><description></description><atom:link href="https://austinrochford.com/tags/testing.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2022 &lt;a href="mailto:austin.rochford@gmail.com"&gt;Austin Rochford&lt;/a&gt; </copyright><lastBuildDate>Mon, 17 Jan 2022 11:51:48 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Verifying Typeclass Laws in Haskell with QuickCheck</title><link>https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html</link><dc:creator>Austin Rochford</dc:creator><description>&lt;p&gt;Recently, I was somewhat idly thinking about how to verify that Haskell typeclasses satisfy the appropriate laws. My first thought was to use equational reasoning to prove that the laws hold. For example, to verify that the left identity law holds for the &lt;code&gt;Maybe&lt;/code&gt; monad, we can show that&lt;/p&gt;
&lt;div class="sourceCode" id="cb1"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb1-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb1-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;return&lt;/span&gt; x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; f &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Just&lt;/span&gt; x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; f &lt;span class="ot"&gt;=&lt;/span&gt; f x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;While this proof is simple (due to the simplicity of the &lt;code&gt;Maybe&lt;/code&gt; monad), I wanted a solution expressed in executable Haskell that could be included in a test suite. As with many Haskell testing problems, &lt;a href="http://hackage.haskell.org/package/QuickCheck"&gt;&lt;code&gt;QuickCheck&lt;/code&gt;&lt;/a&gt; seemed to be a natural solution. In this post, I’ll show how to verify typeclass laws using &lt;code&gt;QuickCheck&lt;/code&gt; for the classes &lt;code&gt;Monoid&lt;/code&gt;, &lt;code&gt;Functor&lt;/code&gt;, and &lt;code&gt;Monad&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id="monoids"&gt;Monoids&lt;/h4&gt;
&lt;p&gt;The definition of the &lt;code&gt;Monoid&lt;/code&gt; typeclass is&lt;/p&gt;
&lt;div class="sourceCode" id="cb2"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb2-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb2-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; &lt;span class="dt"&gt;Monoid&lt;/span&gt; a &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb2-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb2-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;  mappend ::&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; a&lt;/span&gt;
&lt;span id="cb2-3"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb2-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;  mempty ::&lt;/span&gt; a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The module &lt;a href="http://hackage.haskell.org/package/base-4.7.0.0/docs/Data-Monoid.html"&gt;&lt;code&gt;Data.Monoid&lt;/code&gt;&lt;/a&gt; defines the infix operator &lt;code&gt;(&amp;lt;&amp;gt;)&lt;/code&gt; as a synonym for &lt;code&gt;mappend&lt;/code&gt;. We will use the more consise operator form here.&lt;/p&gt;
&lt;p&gt;An instance of &lt;code&gt;Monoid&lt;/code&gt; must satisy the associative law&lt;/p&gt;
&lt;div class="sourceCode" id="cb3"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb3-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb3-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; (y &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; z) &lt;span class="op"&gt;==&lt;/span&gt; (x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; y) &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; z&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and the identity laws&lt;/p&gt;
&lt;div class="sourceCode" id="cb4"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb4-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb4-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;mempty&lt;/span&gt; &lt;span class="op"&gt;==&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;div class="sourceCode" id="cb5"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb5-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb5-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;mempty&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; x &lt;span class="op"&gt;==&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We begin by writing a proposition to test the assocative law, which is fairly straightforward.&lt;/p&gt;
&lt;div class="sourceCode" id="cb6"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb6-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;{-# LANGUAGE ViewPatterns #-}&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-3"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;module&lt;/span&gt; &lt;span class="dt"&gt;Laws&lt;/span&gt; &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-4"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-5"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Control.Applicative&lt;/span&gt; ((&amp;lt;$&amp;gt;))&lt;/span&gt;
&lt;span id="cb6-6"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-7"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Data.Monoid&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-8"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-9"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-9" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Test.QuickCheck&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-10"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-10" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Test.QuickCheck.Function&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-11"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-11" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;import&lt;/span&gt; &lt;span class="dt"&gt;Test.QuickCheck.Gen&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-12"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-12" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb6-13"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-13" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;monoidAssocProp ::&lt;/span&gt; (&lt;span class="dt"&gt;Eq&lt;/span&gt; m, &lt;span class="dt"&gt;Monoid&lt;/span&gt; m) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; m &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; m &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; m &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb6-14"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb6-14" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;monoidAssocProp x y z &lt;span class="ot"&gt;=&lt;/span&gt; (x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; (y &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; z)) &lt;span class="op"&gt;==&lt;/span&gt; ((x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; y) &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; z)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can use this code to test the &lt;code&gt;Monoid&lt;/code&gt; instance of &lt;code&gt;[Int]&lt;/code&gt; as follows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb7"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb7-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb7-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monoidAssocProp ::&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb7-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb7-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is important to include the type annotation, as &lt;code&gt;monoidAssocProp&lt;/code&gt; is written to be applicable to any monoid (technically any monoid that is also an instance of &lt;code&gt;Eq&lt;/code&gt;, but this restriction is not too onerous).&lt;/p&gt;
&lt;p&gt;Similarly, we can test the right and left identity laws as follows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb8"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb8-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb8-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;monoidRightIdProp ::&lt;/span&gt; (&lt;span class="dt"&gt;Eq&lt;/span&gt; m, &lt;span class="dt"&gt;Monoid&lt;/span&gt; m) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; m &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb8-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;monoidRightIdProp x &lt;span class="ot"&gt;=&lt;/span&gt; x &lt;span class="op"&gt;==&lt;/span&gt; (x &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; &lt;span class="fu"&gt;mempty&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb8-3"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb8-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb8-4"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb8-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;monoidLeftIdProp ::&lt;/span&gt; (&lt;span class="dt"&gt;Eq&lt;/span&gt; m, &lt;span class="dt"&gt;Monoid&lt;/span&gt; m) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; m &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb8-5"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb8-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;monoidLeftIdProp x &lt;span class="ot"&gt;=&lt;/span&gt; (&lt;span class="fu"&gt;mempty&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;&amp;gt;&lt;/span&gt; x) &lt;span class="op"&gt;==&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="sourceCode" id="cb9"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb9-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb9-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monoidRightIdProp ::&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb9-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb9-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb9-3"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb9-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb9-4"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb9-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monoidLeftIdProp ::&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb9-5"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb9-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;At this point, we can feel reasonable sure that the &lt;code&gt;Monoid&lt;/code&gt; instance of &lt;code&gt;[Int]&lt;/code&gt; satisfies the monoid laws. &lt;code&gt;QuickCheck&lt;/code&gt; supports testing many monoids out-of-the-box in this manner, but others require more work on our part.&lt;/p&gt;
&lt;p&gt;Suppose we would like to check the monoid laws for &lt;code&gt;Sum Int&lt;/code&gt;. (Recall that &lt;code&gt;mappend&lt;/code&gt; for &lt;code&gt;Sum Int&lt;/code&gt; is addition and &lt;code&gt;mempty&lt;/code&gt; is zero.)&lt;/p&gt;
&lt;div class="sourceCode" id="cb10"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb10-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb10-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monoidRightIdProp ::&lt;/span&gt; &lt;span class="dt"&gt;Sum&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unfortunately, this command fails with the following message.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;No instance for (Arbitrary (Sum Int))
  arising from a use of `quickCheck'
Possible fix: add an instance declaration for (Arbitrary (Sum Int))
In the expression:
  quickCheck (monoidRightIdProp :: Sum Int -&amp;gt; Bool)
In an equation for `it':
    it = quickCheck (monoidRightIdProp :: Sum Int -&amp;gt; Bool)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In order to generate test cases, &lt;code&gt;QuickCheck&lt;/code&gt; requires the arguments of our proposition to be instances of the &lt;code&gt;Arbitrary&lt;/code&gt; class. Fortunately, since &lt;code&gt;Int&lt;/code&gt; is an instance of &lt;code&gt;Arbitrary&lt;/code&gt;, we can quickly make &lt;code&gt;Sum Int&lt;/code&gt; an instance of arbitrary as well. In fact, for any data type &lt;code&gt;a&lt;/code&gt; which is an instance of &lt;code&gt;Arbitrary&lt;/code&gt;, we will make &lt;code&gt;Sum a&lt;/code&gt; an instance of &lt;code&gt;Arbitrary&lt;/code&gt; as well.&lt;/p&gt;
&lt;div class="sourceCode" id="cb12"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb12-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb12-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;instance&lt;/span&gt; (&lt;span class="dt"&gt;Arbitrary&lt;/span&gt; a) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Arbitrary&lt;/span&gt; (&lt;span class="dt"&gt;Sum&lt;/span&gt; a) &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb12-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb12-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;    arbitrary &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="dt"&gt;Sum&lt;/span&gt; &lt;span class="op"&gt;&amp;lt;$&amp;gt;&lt;/span&gt; arbitrary&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we can verify the monoid laws for &lt;code&gt;Sum Int&lt;/code&gt;.&lt;/p&gt;
&lt;div class="sourceCode" id="cb13"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb13-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb13-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monoidAssocProp ::&lt;/span&gt; &lt;span class="dt"&gt;Sum&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Sum&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Sum&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb13-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb13-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-3"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb13-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-4"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb13-4" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monoidRightIdProp ::&lt;/span&gt; &lt;span class="dt"&gt;Sum&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb13-5"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb13-5" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb13-6"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb13-6" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id="cb13-7"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb13-7" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monoidLeftIdProp ::&lt;/span&gt; &lt;span class="dt"&gt;Sum&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb13-8"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb13-8" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="functors"&gt;Functors&lt;/h4&gt;
&lt;p&gt;Even considering the need to define &lt;code&gt;Arbitrary&lt;/code&gt; instances for some &lt;code&gt;Monoid&lt;/code&gt;s, testing the monoid laws was fairly straightforward. Testing the functor laws with &lt;code&gt;QuickCheck&lt;/code&gt; is a bit more involved, due to the need to generate random functions between &lt;code&gt;Arbitrary&lt;/code&gt; instances.&lt;/p&gt;
&lt;p&gt;The definition of the &lt;code&gt;Functor&lt;/code&gt; typeclass is&lt;/p&gt;
&lt;div class="sourceCode" id="cb14"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb14-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb14-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; &lt;span class="dt"&gt;Functor&lt;/span&gt; f &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb14-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb14-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;    fmap ::&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f b&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An instance of &lt;code&gt;Functor&lt;/code&gt; must satisfy the identity law&lt;/p&gt;
&lt;div class="sourceCode" id="cb15"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb15-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb15-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;fmap&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;and the composition law&lt;/p&gt;
&lt;div class="sourceCode" id="cb16"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb16-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb16-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;fmap&lt;/span&gt; (f &lt;span class="op"&gt;.&lt;/span&gt; g) &lt;span class="ot"&gt;=&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; f &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Testing the identity law is relatively simple, since it does not involve arbitrary functions.&lt;/p&gt;
&lt;div class="sourceCode" id="cb17"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb17-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb17-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;functorIdProp ::&lt;/span&gt; (&lt;span class="dt"&gt;Functor&lt;/span&gt; f, &lt;span class="dt"&gt;Eq&lt;/span&gt; (f a)) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb17-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb17-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;functorIdProp x &lt;span class="ot"&gt;=&lt;/span&gt; (&lt;span class="fu"&gt;fmap&lt;/span&gt; &lt;span class="fu"&gt;id&lt;/span&gt; x) &lt;span class="op"&gt;==&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can test the identity law for the &lt;code&gt;Maybe&lt;/code&gt; functor applied to &lt;code&gt;String&lt;/code&gt;s.&lt;/p&gt;
&lt;div class="sourceCode" id="cb18"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb18-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb18-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;functorIdProp ::&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb18-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb18-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Testing the composition law is a bit more complicated, as &lt;code&gt;f :: a -&amp;gt; b&lt;/code&gt; and &lt;code&gt;g :: b -&amp;gt; c&lt;/code&gt; may be arbitrary functions. Fortunately, &lt;a href="http://hackage.haskell.org/package/QuickCheck-2.7.3/docs/Test-QuickCheck-Function.html"&gt;&lt;code&gt;Test.QuickCheck.Function&lt;/code&gt;&lt;/a&gt; provides a way to generate arbitrary functions &lt;code&gt;a -&amp;gt; b&lt;/code&gt; (as long as &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are instances of appropriate typeclasses). The &lt;code&gt;Fun&lt;/code&gt; data type from this module represents an arbitrary function. With this module, we can write a proposition testing the composition law as follows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb19"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb19-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb19-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;functorCompProp ::&lt;/span&gt; (&lt;span class="dt"&gt;Functor&lt;/span&gt; f, &lt;span class="dt"&gt;Eq&lt;/span&gt; (f c)) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; f a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; a b &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; b c &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb19-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb19-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;functorCompProp x (apply &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f) (apply &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; g) &lt;span class="ot"&gt;=&lt;/span&gt; (&lt;span class="fu"&gt;fmap&lt;/span&gt; (g &lt;span class="op"&gt;.&lt;/span&gt; f) x) &lt;span class="op"&gt;==&lt;/span&gt; (&lt;span class="fu"&gt;fmap&lt;/span&gt; g &lt;span class="op"&gt;.&lt;/span&gt; &lt;span class="fu"&gt;fmap&lt;/span&gt; f &lt;span class="op"&gt;$&lt;/span&gt; x)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we use a &lt;a href="https://www.fpcomplete.com/school/to-infinity-and-beyond/pick-of-the-week/guide-to-ghc-extensions/pattern-and-guard-extensions#viewpatterns"&gt;view pattern&lt;/a&gt; to extract a function &lt;code&gt;a -&amp;gt; b&lt;/code&gt; from the second argument, which has type &lt;code&gt;Fun a b&lt;/code&gt;, using the &lt;code&gt;apply&lt;/code&gt; function. We similarly use a view pattern to extract a function &lt;code&gt;b -&amp;gt; c&lt;/code&gt; from the third argument.&lt;/p&gt;
&lt;p&gt;We can use this function to test the composition law for the list functor applied to &lt;code&gt;Int&lt;/code&gt; with two functions &lt;code&gt;Int -&amp;gt; Int&lt;/code&gt; as follows&lt;/p&gt;
&lt;div class="sourceCode" id="cb20"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb20-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb20-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;functorCompProp ::&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb20-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb20-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The test &lt;code&gt;functorCompProp&lt;/code&gt; is rather flexible. We can test the &lt;code&gt;Functor&lt;/code&gt; instance of &lt;code&gt;Maybe&lt;/code&gt;, staring with &lt;code&gt;Int&lt;/code&gt; and involving arbitrary functions &lt;code&gt;Int -&amp;gt; String&lt;/code&gt; and &lt;code&gt;String -&amp;gt; Double&lt;/code&gt; as follows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb21"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb21-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb21-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;functorCompProp ::&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;Double&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb21-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb21-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For certain types, this test may take a while to run, as generating arbitrary functions can take some time for the right (or wrong, depending on your point of view) combination of domain and range types.&lt;/p&gt;
&lt;h4 id="monads"&gt;Monads&lt;/h4&gt;
&lt;p&gt;As with functors, testing the monad laws relies heavily on the &lt;code&gt;Arbitrary&lt;/code&gt; instance of &lt;code&gt;Fun&lt;/code&gt;, with slightly more complicated types.&lt;/p&gt;
&lt;p&gt;The definition of the &lt;code&gt;Monad&lt;/code&gt; typeclass is&lt;/p&gt;
&lt;div class="sourceCode" id="cb22"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb22-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb22-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="kw"&gt;class&lt;/span&gt; &lt;span class="dt"&gt;Monad&lt;/span&gt; m &lt;span class="kw"&gt;where&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb22-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb22-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;    (&amp;gt;&amp;gt;=) ::&lt;/span&gt; m a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; (a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; m b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; m b&lt;/span&gt;
&lt;span id="cb22-3"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb22-3" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;    return ::&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; m a&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An instance of &lt;code&gt;Monad&lt;/code&gt; must satisfy three laws. The first is the right identity law,&lt;/p&gt;
&lt;div class="sourceCode" id="cb23"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb23-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb23-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="fu"&gt;return&lt;/span&gt; &lt;span class="ot"&gt;=&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The second is the left identity law,&lt;/p&gt;
&lt;div class="sourceCode" id="cb24"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb24-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb24-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="fu"&gt;return&lt;/span&gt; x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; f &lt;span class="ot"&gt;=&lt;/span&gt; f x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The third is the associative law,&lt;/p&gt;
&lt;div class="sourceCode" id="cb25"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb25-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb25-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;(x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; f) &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; g &lt;span class="ot"&gt;=&lt;/span&gt; x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; (\x' &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f x' &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; g)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Testing the right identity law is fairly straightforward, because it involves no arbitrary functions.&lt;/p&gt;
&lt;div class="sourceCode" id="cb26"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb26-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb26-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;monadRightIdProp ::&lt;/span&gt; (&lt;span class="dt"&gt;Monad&lt;/span&gt; m, &lt;span class="dt"&gt;Eq&lt;/span&gt; (m a)) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; m a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb26-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb26-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;monadRightIdProp x &lt;span class="ot"&gt;=&lt;/span&gt; (x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; &lt;span class="fu"&gt;return&lt;/span&gt;) &lt;span class="op"&gt;==&lt;/span&gt; x&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can test the right identity law for the type &lt;code&gt;Either String Int&lt;/code&gt; (recall that &lt;code&gt;Either a&lt;/code&gt; is a monad) as follows&lt;/p&gt;
&lt;div class="sourceCode" id="cb27"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb27-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb27-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monadRightIdProp ::&lt;/span&gt; &lt;span class="dt"&gt;Either&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb27-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb27-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Since the left identity law only involves one arbitrary function, it is slightly simpler to test than the associative law.&lt;/p&gt;
&lt;div class="sourceCode" id="cb28"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb28-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb28-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;monadLeftIdProp ::&lt;/span&gt; (&lt;span class="dt"&gt;Monad&lt;/span&gt; m, &lt;span class="dt"&gt;Eq&lt;/span&gt; (m b)) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; a (m b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb28-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb28-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;monadLeftIdProp x (apply &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f) &lt;span class="ot"&gt;=&lt;/span&gt; (&lt;span class="fu"&gt;return&lt;/span&gt; x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; f) &lt;span class="op"&gt;==&lt;/span&gt; (f x)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can verify the left identity law for &lt;code&gt;[Int]&lt;/code&gt; as follows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb29"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb29-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb29-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monadLeftIdProp ::&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;] &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb29-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb29-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally, we write a test for the associative property.&lt;/p&gt;
&lt;div class="sourceCode" id="cb30"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb30-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb30-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="ot"&gt;monadAssocProp ::&lt;/span&gt; (&lt;span class="dt"&gt;Monad&lt;/span&gt; m, &lt;span class="dt"&gt;Eq&lt;/span&gt; (m c)) &lt;span class="ot"&gt;=&amp;gt;&lt;/span&gt; m a &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; a (m b) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; b (m c) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;&lt;/span&gt;
&lt;span id="cb30-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb30-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;monadAssocProp x (apply &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f) (apply &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; g) &lt;span class="ot"&gt;=&lt;/span&gt; ((x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; f) &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; g) &lt;span class="op"&gt;==&lt;/span&gt; (x &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; (\x' &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; f x' &lt;span class="op"&gt;&amp;gt;&amp;gt;=&lt;/span&gt; g))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can verify the associative law for the &lt;code&gt;Maybe&lt;/code&gt; monad and functions &lt;code&gt;f :: Int -&amp;gt; Maybe [Int]&lt;/code&gt; and &lt;code&gt;g :: [Int] -&amp;gt; Maybe String&lt;/code&gt; as follows.&lt;/p&gt;
&lt;div class="sourceCode" id="cb31"&gt;&lt;pre class="sourceCode haskell"&gt;&lt;code class="sourceCode haskell"&gt;&lt;span id="cb31-1"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb31-1" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;&amp;gt;&lt;/span&gt; quickCheck (&lt;span class="ot"&gt;monadAssocProp ::&lt;/span&gt; &lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; &lt;span class="dt"&gt;Int&lt;/span&gt; (&lt;span class="dt"&gt;Maybe&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;]) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Fun&lt;/span&gt; [&lt;span class="dt"&gt;Int&lt;/span&gt;] (&lt;span class="dt"&gt;Maybe&lt;/span&gt; &lt;span class="dt"&gt;String&lt;/span&gt;) &lt;span class="ot"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="dt"&gt;Bool&lt;/span&gt;)&lt;/span&gt;
&lt;span id="cb31-2"&gt;&lt;a href="https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html#cb31-2" aria-hidden="true" tabindex="-1"&gt;&lt;/a&gt;&lt;span class="op"&gt;+++&lt;/span&gt; &lt;span class="dt"&gt;OK&lt;/span&gt;, passed &lt;span class="dv"&gt;100&lt;/span&gt; tests&lt;span class="op"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This post is written in &lt;a href="http://www.haskell.org/haskellwiki/Literate_programming"&gt;literate Haskell&lt;/a&gt; and the source available on &lt;a href="https://github.com/AustinRochford/quickcheck-laws"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;</description><category>Haskell</category><category>Testing</category><guid>https://austinrochford.com/posts/2014-05-27-quickcheck-laws.html</guid><pubDate>Tue, 27 May 2014 04:00:00 GMT</pubDate></item></channel></rss>