nomeata’s mind shares
http://www.joachim-breitner.de//blog
Joachim Breitners Denkblogadehttp://joachim-breitner.de/avatars/avatar_128.pngnomeata’s mind shares
http://www.joachim-breitner.de//blog
128128Isabelle functions: Always total, sometimes undefined
http://www.joachim-breitner.de/blog/732-Isabelle_functions__Always_total%2C_sometimes_undefined
http://www.joachim-breitner.de/blog/732-Isabelle_functions__Always_total%2C_sometimes_undefinedhttp://www.joachim-breitner.de/blog/732-Isabelle_functions__Always_total%2C_sometimes_undefined#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Often, when I mention how things work in the interactive theorem prover [Isabelle/HOL] (in the following just “Isabelle”<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>) to people with a strong background in functional programming (whether that means Haskell or Coq or something else), I cause confusion, especially around the issue of <em>what is a function</em>, are function <em>total</em> and what is the business with <em>undefined</em>. In this blog post, I want to explain some these issues, aimed at functional programmers or type theoreticians.</p>
<p>Note that this is not meant to be a tutorial; I will not explain how to do these things, and will focus on what they mean.</p>
<h3 id="hol-is-a-logic-of-total-functions">HOL is a logic of total functions</h3>
<p>If I have a Isabelle function <code>f :: a ⇒ b</code> between two types <code>a</code> and <code>b</code> (the function arrow in Isabelle is <code>⇒</code>, not <code>→</code>), then – by definition of what it means to be a function in HOL – whenever I have a value <code>x :: a</code>, then the expression <code>f x</code> (i.e. <code>f</code> applied to <code>x</code>) <em>is</em> a value of type <code>b</code>. Therefore, and without exception, <em>every Isabelle function is total</em>.</p>
<p>In particular, it cannot be that <code>f x</code> does not exist for some <code>x :: a</code>. This is a first difference from Haskell, which does have partial functions like</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">spin ::</span> <span class="dt">Maybe</span> <span class="dt">Integer</span> <span class="ot">-></span> <span class="dt">Bool</span>
spin (<span class="dt">Just</span> n) <span class="fu">=</span> spin (<span class="dt">Just</span> (n<span class="fu">+</span><span class="dv">1</span>))</code></pre>
<p>Here, neither the expression <code>spin Nothing</code> nor the expression <code>spin (Just 42)</code> produce a value of type <code>Bool</code>: The former raises an exception (“incomplete pattern match”), the latter does not terminate. Confusingly, though, both expressions have type <code>Bool</code>.</p>
<p>Because every function is total, this confusion cannot arise in Isabelle: If an expression <code>e</code> has type <code>t</code>, then it <em>is</em> a value of type <code>t</code>. This trait is shared with other total systems, including Coq.</p>
<p>Did you notice the emphasis I put on the word “is” here, and how I deliberately did not write “evaluates to” or “returns”? This is because of another big source for confusion:</p>
<h3 id="isabelle-functions-do-not-compute">Isabelle functions do not compute</h3>
<p>We (i.e., functional programmers) stole the word “function” from mathematics and repurposed it<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a>. But the word “function”, in the context of Isabelle, refers to the mathematical concept of a function, and it helps to keep that in mind.</p>
<p>What is the difference?</p>
<ul>
<li>A function <code>a → b</code> in functional programming is an algorithm that, given a value of type <code>a</code>, calculates (returns, evaluates to) a value of type <code>b</code>.</li>
<li>A function <code>a ⇒ b</code> in math (or Isabelle) associates with each value of type <code>a</code> a value of type <code>b</code>.</li>
</ul>
<p>For example, the following is a perfectly valid function definition in math (and HOL), but could not be a function in the programming sense:</p>
<pre class="isabelle"><code>definition foo :: "(nat ⇒ real) ⇒ real" where
"foo seq = (if convergent seq then lim seq else 0)"</code></pre>
<p>This assigns a real number to every sequence, but it does not <em>compute</em> it in any useful sense.</p>
<p>From this it follows that</p>
<h3 id="isabelle-functions-are-specified-not-defined">Isabelle functions are specified, not defined</h3>
<p>Consider this function definition:</p>
<pre class="isabelle"><code>fun plus :: "nat ⇒ nat ⇒ nat" where
"plus 0 m = m"
| "plus (Suc n) m = Suc (plus n m)"</code></pre>
<p>To a functional programmer, this reads</p>
<blockquote>
<p><code>plus</code> is a function that analyses its first argument. If that is <code>0</code>, then it returns the second argument. Otherwise, it calls itself with the predecessor of the first argument and increases the result by one.</p>
</blockquote>
<p>which is clearly a description of a computation.</p>
<p>But to Isabelle, the above reads</p>
<blockquote>
<p><code>plus</code> is a binary function on natural numbers, and it satisfies the following two equations: …</p>
</blockquote>
<p>And in fact, it is not so much Isabelle that reads it this way, but rather the <code>fun</code> command, which is external to the Isabelle logic. The <code>fun</code> command analyses the given equations, constructs a non-recursive definition of <code>plus</code> under the hood, passes <em>that</em> to Isabelle and then proves that the given equations hold for <code>plus</code>.</p>
<p>One interesting consequence of this is that different specifications can lead to the same functions. In fact, if we would define <code>plus'</code> by recursing on the second argument, we’d obtain the the same function (i.e. <code>plus = plus'</code> is a theorem, and there would be no way of telling the two apart).</p>
<h3 id="termination-is-a-property-of-specifications-not-functions">Termination is a property of specifications, not functions</h3>
<p>Because a function does not evaluate, it does not make sense to ask if it terminates. The question of termination arises <em>before</em> the function is defined: The <code>fun</code> command can only construct <code>plus</code> in a way that the equations hold if it passes a termination check – very much like <code>Fixpoint</code> in Coq.</p>
<p>But while the termination check of <code>Fixpoint</code> in Coq is a deep part of the basic logic, in Isabelle it is simply something that this particular command requires for its internal machinery to go through. At no point does a “termination proof of the function” exist as a theorem inside the logic. And other commands may have other means of defining a function that do not even require such a termination argument!</p>
<p>For example, a function specification that is tail-recursive can be turned in to a function, even without a termination proof: The following definition describes a higher-order function that iterates its first argument <code>f</code> on the second argument <code>x</code> until it finds a fixpoint. It is completely polymorphic (the single quote in <code>'a</code> indicates that this is a type variable):</p>
<pre class="isabelle"><code>partial_function (tailrec)
fixpoint :: "('a ⇒ 'a) ⇒ 'a ⇒ 'a"
where
"fixpoint f x = (if f x = x then x else fixpoint f (f x))"</code></pre>
<p>We can work with this definition just fine. For example, if we instantiate <code>f</code> with <code>(λx. x-1)</code>, we can prove that it will always return 0:</p>
<pre class="isabelle"><code>lemma "fixpoint (λ n . n - 1) (n::nat) = 0"
by (induction n) (auto simp add: fixpoint.simps)</code></pre>
<p>Similarly, if we have a function that works within the option monad (i.e. |Maybe| in Haskell), its specification can always be turned into a function without an explicit termination proof – here one that calculates the Collatz sequence:</p>
<pre class="isabelle"><code>partial_function (option) collatz :: "nat ⇒ nat list option"
where "collatz n =
(if n = 1 then Some [n]
else if even n
then do { ns <- collatz (n div 2); Some (n # ns) }
else do { ns <- collatz (3 * n + 1); Some (n # ns)})"</code></pre>
<p>Note that lists in Isabelle are finite (like in Coq, unlike in Haskell), so this function “returns” a list only if the collatz sequence eventually reaches 1.</p>
<p>I expect these definitions to make a Coq user very uneasy. How can <code>fixpoint</code> be a total function? What is <code>fixpoint (λn. n+1)</code>? What if we run <code>collatz n</code> for a <code>n</code> where the <a href="https://en.wikipedia.org/wiki/Collatz_conjecture">Collatz sequence</a> does <em>not</em> reach 1?<a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a> We will come back to that question after a little detour…</p>
<h3 id="hol-is-a-logic-of-non-empty-types">HOL is a logic of non-empty types</h3>
<p>Another big difference between Isabelle and Coq is that in Isabelle, <em>every type is inhabited</em>. Just like the totality of functions, this is a very fundamental fact about what HOL defines to be a type.</p>
<p>Isabelle gets away with that design because in Isabelle, we do not use types for propositions (like we do in Coq), so we do not need empty types to denote false propositions.</p>
<p>This design has an important consequence: It allows the existence of a polymorphic expression that inhabits any type, namely</p>
<pre class="isabelle"><code>undefined :: 'a</code></pre>
<p>The naming of this term alone has caused a great deal of confusion for Isabelle beginners, or in communication with users of different systems, so I implore you to not read too much into the name. In fact, you will have a better time if you think of it as <code>arbitrary</code> or, even better, <code>unknown</code>.</p>
<p>Since <code>undefined</code> can be instantiated at any type, we can instantiate it for example at <code>bool</code>, and we can observe an important fact: <code>undefined</code> is not an <em>extra</em> value besides the “usual ones”. It is simply <em>some</em> value of that type, which is demonstrated in the following lemma:</p>
<pre class="isabelle"><code>lemma "undefined = True ∨ undefined = False" by auto</code></pre>
<p>In fact, if the type has only one value (such as the unit type), then we know the value of <code>undefined</code> for sure:</p>
<pre class="isabelle"><code>lemma "undefined = ()" by auto</code></pre>
<p>It is very handy to be able to produce an expression of any type, as we will see as follows</p>
<h3 id="partial-functions-are-just-underspecified-functions">Partial functions are just underspecified functions</h3>
<p>For example, it allows us to translate incomplete function specifications. Consider this definition, Isabelle’s equivalent of Haskell’s partial <code>fromJust</code> function:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell">fun fromSome :: <span class="st">"'a option ⇒ 'a"</span> <span class="kw">where</span>
<span class="st">"fromSome (Some x) = x"</span></code></pre>
<p>This definition is accepted by <code>fun</code> (albeit with a warning), and the generated function <code>fromSome</code> behaves exactly as specified: when applied to <code>Some x</code>, it is <code>x</code>. The term <code>fromSome None</code> is also a value of type <code>'a</code>, we just do not know which one it is, as the specification does not address that.</p>
<p>So <code>fromSome None</code> behaves just like <code>undefined</code> above, i.e. we can prove</p>
<pre class="isabelle"><code>lemma "fromSome None = False ∨ fromSome None = True" by auto</code></pre>
<p>Here is a small exercise for you: Can you come up with an explanation for the following lemma:</p>
<pre class="isabelle"><code>fun constOrId :: "bool ⇒ bool" where
"constOrId True = True"
lemma "constOrId = (λ_.True) ∨ constOrId = (λx. x)"
by (metis (full_types) constOrId.simps)</code></pre>
<p>Overall, this behavior makes sense if we remember that function “definitions” in Isabelle are not really definitions, but rather specifications. And a partial function “definition” is simply a underspecification. The resulting function is simply any function hat fulfills the specification, and the two lemmas above underline that observation.</p>
<h3 id="nonterminating-functions-are-also-just-underspecified">Nonterminating functions are also just underspecified</h3>
<p>Let us return to the puzzle posed by <code>fixpoint</code> above. Clearly, the function – seen as a functional program – is not total: When passed the argument <code>(λn. n + 1)</code> or <code>(λb. ¬b)</code> it will loop forever trying to find a fixed point.</p>
<p>But Isabelle functions are not functional programs, and the definitions are just specifications. What does the specification say about the case when <code>f</code> has no fixed-point? It states that the equation <code>fixpoint f x = fixpoint f (f x)</code> holds. And this equation has a solution, for example <code>fixpoint f _ = undefined</code>.</p>
<p>Or more concretely: The specification of the <code>fixpoint</code> function states that <code>fixpoint (λb. ¬b) True = fixpoint (λb. ¬b) False</code> has to hold, but it does not specify which particular value (<code>True</code> or <code>False</code>) it should denote – any is fine.</p>
<h3 id="not-all-function-specifications-are-ok">Not all function specifications are ok</h3>
<p>At this point you might wonder: Can I just specify any equations for a function <code>f</code> and get a function out of that? But rest assured: That is not the case. For example, no Isabelle command allows you define a function <code>bogus :: () ⇒ nat</code> with the equation <code>bogus () = Suc (bogus ())</code>, because this equation does not have a solution.</p>
<p>We can actually prove that such a function cannot exist:</p>
<pre class="isabelle"><code>lemma no_bogus: "∄ bogus. bogus () = Suc (bogus ())" by simp</code></pre>
<p>(Of course, <code>not_bogus () = not_bogus ()</code> is just fine…)</p>
<h3 id="you-cannot-reason-about-partiality-in-isabelle">You cannot reason about partiality in Isabelle</h3>
<p>We have seen that there are many ways to define functions that one might consider “partial”. Given a function, can we prove that it is not “partial” in that sense?</p>
<p>Unfortunately, but unavoidably, no: Since <code>undefined</code> is not a separate, recognizable value, but rather simply an unknown one, there is no way of stating that “A function result is not specified”.</p>
<p>Here is an example that demonstrates this: Two “partial” functions (one with not all cases specified, the other one with a self-referential specification) are indistinguishable from the total variant:</p>
<pre class="isabelle"><code>fun partial1 :: "bool ⇒ unit" where
"partial1 True = ()"
partial_function (tailrec) partial2 :: "bool ⇒ unit" where
"partial2 b = partial2 b"
fun total :: "bool ⇒ unit" where
"total True = ()"
| "total False = ()"
lemma "partial1 = total ∧ partial2 = total" by auto</code></pre>
<p>If you really <em>do</em> want to reason about partiality of functional programs in Isabelle, you should consider implementing them not as plain HOL functions, but rather use <a href="http://isabelle.in.tum.de/dist/library/HOL/HOLCF/README.html">HOLCF</a>, where you can give equational specifications of functional programs and obtain <em>continuous functions</em> between <em>domains</em>. In that setting, <code>⊥ ≠ ()</code> and <code>partial2 = ⊥ ≠ total</code>. We have done that <a href="https://arxiv.org/abs/1306.1340">to verify some of HLint’s equations</a>.</p>
<h3 id="you-can-still-compute-with-isabelle-functions">You can still compute with Isabelle functions</h3>
<p>I hope by this point, I have not scared away anyone who wants to use Isabelle for functional programming, and in fact, you can use it for that. If the equations that you pass to `fun are a reasonable definition for a function (in the programming sense), then these equations, used as rewriting rules, will allow you to “compute” that function quite like you would in Coq or Haskell.</p>
<p>Moreover, Isabelle supports code extraction: You can take the equations of your Isabelle functions and have them expored into Ocaml, Haskell, Scala or Standard ML. See <a href="http://www21.in.tum.de/~popescua/rs3/CoCon.html">Concon</a> for a conference management system with confidentially verified in Isabelle.</p>
<p>While these usually are the equations you defined the function with, they don't have to: You can declare other proved equations to be used for code extraction, e.g. to refine your elegant definitions to performant ones.</p>
<p>Like with code extraction from Coq to, say, Haskell, the adequacy of the translations rests on a <a href="http://www.cse.chalmers.se/~nad/publications/danielsson-et-al-popl2006.html">“moral reasoning” foundation</a>. Unlike extraction from Coq, where you have an (unformalized) guarantee that the resulting Haskell code is terminating, you do not get that guarantee from Isabelle. Conversely, this allows you do reason about and extract non-terminating programs, like <code>fixpoint</code>, which is not possible in Coq.</p>
<p>There is <a href="https://www21.in.tum.de/~hupel/pub/isabelle-cakeml.pdf">currently ongoing work</a> about verified code generation, where the code equations are reflected into a deep embedding of HOL in Isabelle that would allow explicit termination proofs.</p>
<h3 id="conclusion">Conclusion</h3>
<p>We have seen how in Isabelle, <em>every function is total</em>. Function declarations have equations, but these do not <em>define</em> the function in an computational sense, but rather <em>specify</em> them. Because in HOL, there are no empty types, many specifications that appear partial (incomplete patterns, non-terminating recursion) have solutions in the space of total functions. Partiality in the specification is no longer visible in the final product.</p>
<h3 id="ps-axiom-undefined-in-coq">PS: Axiom <code>undefined</code> in Coq</h3>
<p><em>This section is speculative, and an invitation for discussion.</em></p>
<p>Coq already distinguishes between types used in programs (<code>Set</code>) and types used in proofs <code>Prop</code>.</p>
<p>Could Coq ensure that every <code>t : Set</code> is non-empty? I imagine this would require additional checks in the <code>Inductive</code> command, similar to the checks that the Isabelle command <code>datatype</code> has to perform<a href="#fn4" class="footnoteRef" id="fnref4"><sup>4</sup></a>, and it would disallow <a href="https://coq.inria.fr/library/Coq.Init.Datatypes.html"><code>Empty_set</code></a>.</p>
<p>If so, then it would be sound to add the following axiom</p>
<pre class="coq"><code>Axiom undefined : forall (a : Set), a.</code></pre>
<p>wouldn't it? This axiom does not have any computational meaning, but that seems to be ok for optional Coq axioms, like classical reasoning or function extensionality.</p>
<p>With this in place, how much of what I describe above about function definitions in Isabelle could now be done soundly in Coq. Certainly pattern matches would not have to be complete and could sport an implicit case <code>_ ⇒ undefined</code>. Would it “help” with non-obviously terminating functions? Would it allow a Coq command <code>Tailrecursive</code> that accepts any tailrecursive function without a termination check?</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn1"><p>Isabelle is a metalogical framework, and other logics, e.g. Isabelle/ZF, behave differently. For the purpose of this blog post, I always mean Isabelle/HOL.<a href="#fnref1">↩</a></p></li>
<li id="fn2"><p>Isabelle is a metalogical framework, and other logics, e.g. Isabelle/ZF, behave differently. For the purpose of this blog post, I always mean Isabelle/HOL.<a href="#fnref2">↩</a></p></li>
<li id="fn3"><p>Let me know if you find such an <span class="math"><em>n</em></span>. Besides <span class="math"><em>n</em> = 0</span>.<a href="#fnref3">↩</a></p></li>
<li id="fn4"><p>Like <code>fun</code>, the constructions by <code>datatype</code> are not part of the logic, but create a type definition from more primitive notions that is isomorphic to the specified data type.<a href="#fnref4">↩</a></p></li>
</ol>
</div>Thu, 12 Oct 2017 13:54:20 -0400e.g. in TeX
http://www.joachim-breitner.de/blog/731-e_g__in_TeX
http://www.joachim-breitner.de/blog/731-e_g__in_TeXhttp://www.joachim-breitner.de/blog/731-e_g__in_TeX#commentsmail@joachim-breitner.de (Joachim Breitner)<p>When I learned TeX, I was told to not write <code>e.g. something</code>, because TeX would think the period after the “g” ends a sentence, and introduce a wider, inter-sentence space. Instead, I was to write <code>e.g.\␣</code>.</p>
<p>Years later, I learned from a convincing, but since forgotten source, that in fact <code>e.g.\@</code> is the proper thing to write. I vaguely remembering that <code>e.g.\␣</code> supposedly affected the inter-word space in some unwanted way. So I did that for many years.</p>
<p>Until I recently was called out for doing it wrong, and that infact <code>e.g.\␣</code> is the proper way. This was supported by <a href="https://tex.stackexchange.com/a/22563/15107">a StackExchange answer</a> written by a LaTeX authority and backed by a reference to documentation. The same question has, however, <a href="https://tex.stackexchange.com/a/22564/15107">another answer</a> by another TeX authority, backed by an analysis of the implementation, which concludes that <code>e.g.\@</code> is proper.</p>
<p>What now? I guess I just have to find it out myself.</p>
<div class="figure">
<img src="//www.joachim-breitner.de/various/tex-eg/tex-eg-at-1.gif" alt="The problem and two solutions"/><p class="caption">The problem and two solutions</p>
</div>
<p>The above image shows three variants: The obviously broken version with <code>e.g.</code>, and the two contesting variants to fix it. Looks like they yield equal results!</p>
<p>So maybe the difference lies in how <code>\@</code> and <code>\␣</code> react when the line length changes, and the word wrapping require differences in the inter-word spacing. Will there be differences? Let’s see;</p>
<div class="figure">
<img src="//www.joachim-breitner.de/various/tex-eg/tex-eg-at-2.gif" alt="Expanding whitespace, take 1"/><p class="caption">Expanding whitespace, take 1</p>
</div>
<div class="figure">
<img src="//www.joachim-breitner.de/various/tex-eg/tex-eg-at-3.gif" alt="Expanding whitespace, take 2"/><p class="caption">Expanding whitespace, take 2</p>
</div>
<p>I cannot see any difference. But the inter-sentence whitespace ate most of the expansion. Is there a difference visible if we have only inter-word spacing in the line?</p>
<div class="figure">
<img src="//www.joachim-breitner.de/various/tex-eg/tex-eg-at-4.gif" alt="Expanding whitespace, take 3"/><p class="caption">Expanding whitespace, take 3</p>
</div>
<div class="figure">
<img src="//www.joachim-breitner.de/various/tex-eg/tex-eg-at-5.gif" alt="Expanding whitespace, take 4"/><p class="caption">Expanding whitespace, take 4</p>
</div>
<p>Again, I see the same behaviour.</p>
<p><strong>Conclusion</strong>: It does not matter, but <code>e.g.\␣</code> is less hassle when using <a href="http://hackage.haskell.org/package/lhs2tex">lhs2tex</a> than <code>e.g.\@</code> (which has to be escaped as <code>e.g.\@@</code>), so the winner is <code>e.g.\␣</code>!</p>
<p>(Unless you put it in a macro, <a href="https://tex.stackexchange.com/a/116530/15107">then <code>\@</code> might be preferable</a>, and it is still <a href="https://tex.stackexchange.com/a/55112/15107">needed between a captial letter and a sentence period</a>.)</p>Sun, 08 Oct 2017 15:08:13 -0400Less parentheses
http://www.joachim-breitner.de/blog/730-Less_parentheses
http://www.joachim-breitner.de/blog/730-Less_parentheseshttp://www.joachim-breitner.de/blog/730-Less_parentheses#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Yesterday, at the <a href="http://conf.researchr.org/track/hiw-2017/hiw-2017">Haskell Implementers Workshop 2017</a> in Oxford, I gave a lightning talk titled ”syntactic musings”, where I presented three possibly useful syntactic features that one might want to add to a language like Haskell.</p>
<p>The talked caused quite some heated discussions, and since the Internet likes heated discussion, I will happily share these ideas with you</p>
<h3 id="context-aka.-sections">Context aka. Sections</h3>
<p>This is probably the most relevant of the three proposals. Consider a bunch of related functions, say <code>analyseExpr</code> and <code>analyseAlt</code>, like these:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">analyseExpr ::</span> <span class="dt">Expr</span> <span class="ot">-></span> <span class="dt">Expr</span>
analyseExpr (<span class="dt">Var</span> v) <span class="fu">=</span> change v
analyseExpr (<span class="dt">App</span> e1 e2) <span class="fu">=</span>
<span class="dt">App</span> (analyseExpr e1) (analyseExpr e2)
analyseExpr (<span class="dt">Lam</span> v e) <span class="fu">=</span> <span class="dt">Lam</span> v (analyseExpr flag e)
analyseExpr (<span class="dt">Case</span> scrut alts) <span class="fu">=</span>
<span class="dt">Case</span> (analyseExpr scrut) (analyseAlt <span class="fu"><$></span> alts)
<span class="ot">analyseAlt ::</span> <span class="dt">Alt</span> <span class="ot">-></span> <span class="dt">Alt</span>
analyseAlt (dc, pats, e) <span class="fu">=</span> (dc, pats, analyseExpr e)</code></pre>
<p>You have written them, but now you notice that you need to make them configurable, e.g. to do different things in the <code>Var</code> case. You thus add a parameter to all these functions, and hence an argument to every call:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">Flag</span> <span class="fu">=</span> <span class="dt">Bool</span>
<span class="ot">analyseExpr ::</span> <span class="dt">Flag</span> <span class="ot">-></span> <span class="dt">Expr</span> <span class="ot">-></span> <span class="dt">Expr</span>
analyseExpr flag (<span class="dt">Var</span> v) <span class="fu">=</span> <span class="kw">if</span> flag <span class="kw">then</span> change1 v <span class="kw">else</span> change2 v
analyseExpr flag (<span class="dt">App</span> e1 e2) <span class="fu">=</span>
<span class="dt">App</span> (analyseExpr flag e1) (analyseExpr flag e2)
analyseExpr flag (<span class="dt">Lam</span> v e) <span class="fu">=</span> <span class="dt">Lam</span> v (analyseExpr (not flag) e)
analyseExpr flag (<span class="dt">Case</span> scrut alts) <span class="fu">=</span>
<span class="dt">Case</span> (analyseExpr flag scrut) (analyseAlt flag <span class="fu"><$></span> alts)
<span class="ot">analyseAlt ::</span> <span class="dt">Flag</span> <span class="ot">-></span> <span class="dt">Alt</span> <span class="ot">-></span> <span class="dt">Alt</span>
analyseAlt flag (dc, pats, e) <span class="fu">=</span> (dc, pats, analyseExpr flag e)</code></pre>
<p>I find this code problematic. The intention was: “<code>flag</code> is a parameter that an external caller can use to change the behaviour of this code, but when reading and reasoning about this code, <code>flag</code> should be considered constant.”</p>
<p>But this intention is neither easily visible nor enforced. And in fact, in the above code, <code>flag</code> does “change”, as <code>analyseExpr</code> passes something else in the <code>Lam</code> case. The idiom is indistinguishable from the <em>environment idiom</em>, where a <em>locally changing</em> environment (such as “variables in scope”) is passed around.</p>
<p>So we are facing exactly the same problem as when reasoning about a loop in an imperative program with mutable variables. And we (pure functional programmers) should know better: We cherish immutability! We want to bind our variables once and have them scope over everything we need to scope over!</p>
<p>The solution I’d like to see in Haskell is common in other languages (Gallina, Idris, Agda, Isar), and this is what it would look like here:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="kw">type</span> <span class="dt">Flag</span> <span class="fu">=</span> <span class="dt">Bool</span>
section (<span class="ot">flag ::</span> <span class="dt">Flag</span>) <span class="kw">where</span>
<span class="ot"> analyseExpr ::</span> <span class="dt">Expr</span> <span class="ot">-></span> <span class="dt">Expr</span>
analyseExpr (<span class="dt">Var</span> v) <span class="fu">=</span> <span class="kw">if</span> flag <span class="kw">then</span> change1 v <span class="kw">else</span> change2v
analyseExpr (<span class="dt">App</span> e1 e2) <span class="fu">=</span>
<span class="dt">App</span> (analyseExpr e1) (analyseExpr e2)
analyseExpr (<span class="dt">Lam</span> v e) <span class="fu">=</span> <span class="dt">Lam</span> v (analyseExpr e)
analyseExpr (<span class="dt">Case</span> scrut alts) <span class="fu">=</span>
<span class="dt">Case</span> (analyseExpr scrut) (analyseAlt <span class="fu"><$></span> alts)
<span class="ot"> analyseAlt ::</span> <span class="dt">Alt</span> <span class="ot">-></span> <span class="dt">Alt</span>
analyseAlt (dc, pats, e) <span class="fu">=</span> (dc, pats, analyseExpr e)</code></pre>
<p>Now the intention is clear: Within a clearly marked block, <code>flag</code> is fixed and when reasoning about this code I do not have to worry that it might change. Either <em>all</em> variables will be passed to <code>change1</code>, or <em>all</em> to <code>change2</code>. An important distinction!</p>
<p>Therefore, inside the <code>section</code>, the type of <code>analyseExpr</code> does not mention <code>Flag</code>, whereas outside its type is <code>Flag -> Expr -> Expr</code>. This is a bit unusual, but not completely: You see precisely the same effect in a <code>class</code> declaration, where the type signature of the methods do not mention the class constraint, but outside the declaration they do.</p>
<p>Note that idioms like implicit parameters or the <code>Reader</code> monad do not give the guarantee that the parameter is (locally) constant.</p>
<p>More details can be found in the <a href="https://github.com/ghc-proposals/ghc-proposals/pull/40">GHC proposal</a> that I prepared, and I invite you to raise concern or voice support there.</p>
<p>Curiously, this problem must have bothered me for longer than I remember: I discovered that seven years ago, I wrote a Template Haskell based implementation of this idea in the <a href="http://hackage.haskell.org/package/seal-module"><code>seal-module</code></a> package!</p>
<h3 id="less-parentheses-1-bulleted-argument-lists">Less parentheses 1: Bulleted argument lists</h3>
<p>The next two proposals are all about removing parentheses. I believe that Haskell’s tendency to express complex code with no or few parentheses is one of its big strengths, as it makes it easier to visualy parse programs. A common idiom is to use the <code>$</code> operator to separate a function from a complex argument without parentheses, but it does not help when there are multiple complex arguments.</p>
<p>For that case I propose to steal an idea from the surprisingly successful markup language markdown, and use bulleted lists to indicate multiple arguments:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">foo ::</span> <span class="dt">Baz</span>
foo <span class="fu">=</span> bracket
• some complicated code
that is evaluated first
• other complicated code for later
• even more complicated code</code></pre>
<p>I find this very easy to visually parse and navigate.</p>
<p>It is actually possible to do this now, if one defines <code>(•) = id</code> with <code>infixl 0 •</code>. A dedicated syntax extension (<code>-XArgumentBullets</code>) is preferable:</p>
<ul>
<li>It only really adds readability if the bullets are nicely vertically aligned, which the compiler should enforce.</li>
<li>I would like to use <code>$</code> inside these complex arguments, and multiple operators of precedence 0 do not mix. (<code>infixl -1 •</code> would help).</li>
<li>It should be possible to nest these, and distinguish different nesting levers based on their indentation.</li>
</ul>
<h3 id="less-parentheses-1-whitespace-precedence">Less parentheses 1: Whitespace precedence</h3>
<p>The final proposal is the most daring. I am convinced that it improves readability and should be considered when creating a new language. As for Haskell, I am at the moment not proposing this as a language extension (but could be convinced to do so if there is enough positive feedback).</p>
<p>Consider this definition of append:</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">(++) ::</span> [a] <span class="ot">-></span> [a] <span class="ot">-></span> [a]
[] <span class="fu">++</span> ys <span class="fu">=</span> ys
(x<span class="fu">:</span>xs) <span class="fu">++</span> ys <span class="fu">=</span> x <span class="fu">:</span> (xs<span class="fu">++</span>ys)</code></pre>
<p>Imagine you were explaining the last line to someone orally. How would you speak it? One common way to do so is to not read the parentheses out aloud, but rather speak parenthesised expression more quickly and add pauses otherwise.</p>
<p>We can do the same in syntax!</p>
<pre class="sourceCode haskell"><code class="sourceCode haskell"><span class="ot">(++) ::</span> [a] <span class="ot">-></span> [a] <span class="ot">-></span> [a]
[] <span class="fu">++</span> ys <span class="fu">=</span> ys
x<span class="fu">:</span>xs <span class="fu">++</span> ys <span class="fu">=</span> x <span class="fu">:</span> xs<span class="fu">++</span>ys</code></pre>
<p>The rule is simple: <em>A sequence of tokens without any space is implicitly parenthesised.</em></p>
<p>The reaction I got in Oxford was horror and disgust. And that is understandable – we are very used to ignore spacing when parsing expressions (unless it is indentation, of course. Then we are no longer horrified, as our non-Haskell colleagues are when they see our code).</p>
<p>But I am convinced that once you let the rule sink in, you will have no problem parsing such code with ease, and soon even with greater ease than the parenthesised version. It is a very natural thing to look at the general structure, identify “compact chunks of characters”, mentally group them, and then go and separately parse the internals of the chunks and how the chunks relate to each other. More natural than first scanning everything for <code>(</code> and <code>)</code>, matching them up, building a mental tree, and then digging deeper.</p>
<p>Incidentally, there was a non-programmer present during my presentation, and while she did not openly contradict the dismissive groan of the audience, I later learned that she found this variant quite obvious to understand and more easily to read than the parenthesised code.</p>
<p>Some FAQs about this:</p>
<ul>
<li><em>What about an operator with space on one side but not on the other?</em> I’d simply forbid that, and hence enforce readable code.</li>
<li><em>Do operator sections still require parenthesis?</em> Yes, I’d say so.</li>
<li>Does this overrule operator precedence? Yes! <code>a * b+c == a * (b+c)</code>.</li>
<li><em>What is a token</em>? Good question, and I am not not decided. In particular: Is a parenthesised expression a single token? If so, then <code>(Succ a)+b * c</code> parses as <code>((Succ a)+b) * c</code>, otherwise it should probably simply be illegal.</li>
<li><em>Can we extend this so that one space binds tighter than two spaces, and so on?</em> Yes we can, but really, we should not.</li>
<li><em>This is incompatible with Agda’s syntax!</em> Indeed it is, and I really like Agda’s mixfix syntax. Can’t have everything.</li>
<li><em>Has this been done before?</em> I have not seen it in any language, but <a href="http://wall.org/~lewis/2013/10/25/whitespace-precedence.html">Lewis Wall</a> has blogged this idea before.</li>
</ul>
<p>Well, let me know what you think!</p>Sun, 10 Sep 2017 11:10:16 +0100Compose Conference talk video online
http://www.joachim-breitner.de/blog/729-Compose_Conference_talk_video_online
http://www.joachim-breitner.de/blog/729-Compose_Conference_talk_video_onlinehttp://www.joachim-breitner.de/blog/729-Compose_Conference_talk_video_online#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Three months ago, I gave a talk at the <a href="http://www.composeconference.org/2017/program/">Compose::Conference</a> in New York about how Chris Smith and I added the ability to create networked multi-user programs to the educational Haskell programming environment <a href="https://code.world/">CodeWorld</a>, and finally the recording of the talk is available <a href="https://www.youtube.com/watch?v=2kKvVe673MA">on YouTube</a> (and is being discussed <a href="https://www.reddit.com/r/haskell/comments/6uam49/compose_conference_lock_step_simulation_is_childs/">on reddit</a>):</p>
<iframe src="https://www.youtube.com/embed/2kKvVe673MA?rel=0?ecver=2" width="640" height="360" frameborder="0" style="display: block; margin-left: auto; margin-right: auto">
</iframe>
<p>It was the talk where I got the most positive feedback afterwards, and I think this is partly due to how I created the presentation: Instead of showing static slides, I programmed the complete visual display from scratch as an “interaction” within the CodeWorld environment, including all transitions, an working embedded game of Pong and a simulated multi-player environments with adjustable message delays. I have put the <a href="https://github.com/nomeata/codeworld-talk">code for the presentation</a> online.</p>
<p>Chris and I have written about this for ICFP'17, and thanks to open access I can actually share <a href="https://www.joachim-breitner.de/publications/CodeWorld-ICFP17.pdf">the paper</a> freely with you and under a CC license. If you come to Oxford you can see me perform a shorter version of this talk again.</p>Sun, 20 Aug 2017 20:50:10 +0200Communication Failure
http://www.joachim-breitner.de/blog/728-Communication_Failure
http://www.joachim-breitner.de/blog/728-Communication_Failurehttp://www.joachim-breitner.de/blog/728-Communication_Failure#commentsmail@joachim-breitner.de (Joachim Breitner)<p>I am still far from being a professor, but I recently got a glimpse of what awaits you in that role…</p>
<blockquote>
<p><strong>From:</strong> Sebastian R. <…<span class="citation">@gmail.com</span>><br/><strong>To:</strong> joachim@cis.upenn.edu<br/><strong>Subject:</strong> re: Errors</p>
<p>I've spotted a basic error in your course on Haskell (<a href="https://www.seas.upenn.edu/~cis194/fall16/">https://www.seas.upenn.edu/~cis194/fall16/</a>). Before I proceed, it's cool if you're not receptive to errors being indicated; I've come across a number of professors who would rather take offense than admit we're all human and thus capable of making mistakes... My goal is to find a resource that might be useful well into the future, and a good indicator of that is how responsive the author is to change.</p>
<p>In your introduction note you have written:</p>
<blockquote>
<p>n contrast to a classical intro into Haskell, we do not start with numbers, booleans, tuples, lists and strings, but we start with pictures. These are of course library-defined (hence the input CodeWorld) and not part of “the language”. But that does not make them less interesting, and in fact, even the basic boolean type is library defined – it just happens to be the standard library.</p>
</blockquote>
<p>Howeverm there is no <code>input CodeWorld</code> in the code above. Have you been made aware of this error earlier?</p>
<p>Regards, ...</p>
</blockquote>
<p>Nice. I like when people learn from my lectures. The introduction is a bit werid, but ok, maybe this guy had some bad experiences.</p>
<p>Strangley, I don’t see a mistake in the material, so I respond:</p>
<blockquote>
<p><strong>From:</strong> Joachim Breitner <script type="text/javascript">
</script><noscript>joachim at cis dot upenn dot edu</noscript><br/><strong>To:</strong> Sebastian R. <…<span class="citation">@gmail.com</span>><br/><strong>Subject:</strong> Re: Errors</p>
<p>Dear Sebastian,</p>
<p>thanks for pointing out errors. But the first piece of code under “Basic Haskell” starts with</p>
<pre><code>{-# LANGUAGE OverloadedStrings #-}
import CodeWorld</code></pre>
<p>so I am not sure what you are referring to.</p>
<p>Note that these are lecture notes, so you have to imagine a lecturer editing code live on stage along with it. If you only have the notes, you might have to infer a few things.</p>
<p>Regards, Joachim</p>
</blockquote>
<p>A while later, I receive this response:</p>
<blockquote>
<p><strong>From:</strong> Sebastian R. <…<span class="citation">@gmail.com</span>><br/><strong>To:</strong> Joachim Breitner <script type="text/javascript">
</script><noscript>joachim at cis dot upenn dot edu</noscript><br/><strong>Subject:</strong> Re: Errors</p>
<p>Greetings, Joachim.</p>
<p>Kindly open the lecture slides and search for "input CodeWorld" to find the error; it is not in the code, but in the paragraph that implicitly refers back to the code.</p>
<p>You might note that I quoted this precisely from the lectures... and so I repeat myself... this came from <strong>your</strong> lectures; they're not my words!</p>
<blockquote>
<p>In contrast to a classical intro into Haskell, we do not start with numbers, booleans, tuples, lists and strings, but we start with pictures. These are of course library-defined (hence the <span style="color:red">input CodeWorld</span>) and not part of “the language”. But that does not make them less interesting, and in fact, even the basic boolean type is library defined – it just happens to be the standard library.</p>
</blockquote>
<p>This time around, I've highlighted the issue. I hope that made it easier for you to spot...</p>
<p>Nonetheless, I got my answer. Don't reply if you're going to fight tooth and nail about such a basic fix; it's simply a waste of both of our time. I'd rather learn from somewhere else...</p>
<p>On Tue, Aug 1, 2017 at 11:19 PM, Joachim Breitner <script type="text/javascript">
</script><noscript>joachim at cis dot upenn dot edu</noscript> wrote:<br/>…</p>
</blockquote>
<p>I am a bit reminded of Sean Spicer … “they’re not my words!” … but clearly I am missing something. And indeed I am: In the code snippet, I wrote – correctly – <code>import CodeWorld</code>, but in the text I had <code>input CodeWorld</code>. I probably did write LaTeX before writing the lecture notes. Well, glad to have that sorted out. I fixed the mistake and wrote back:</p>
<blockquote>
<p><strong>From:</strong> Joachim Breitner <script type="text/javascript">
</script><noscript>joachim at cis dot upenn dot edu</noscript><br/><strong>To:</strong> Sebastian R. <…<span class="citation">@gmail.com</span>><br/><strong>Betreff:</strong> Re: Errors</p>
<p>Dear Sebastian,</p>
<p>nobody is fighting, and I see the mistake now: The problem is not that the line is not in the code, the problem is that there is a typo in the line and I wrote “input” instead of “import”.</p>
<p>Thanks for the report, although you did turn it into quite a riddle… a simple “you wrote import when it should have been import” would have been a better user of both our time.</p>
<p>Regards, Joachim</p>
<p>Am Donnerstag, den 03.08.2017, 13:32 +1000 schrieb Sebastian R.:<br/>…</p>
</blockquote>
<p>(And it seems I now made the inverse typo, writing “import“ instead of “input”. Anyways, I did not think of this any more until a few days later, when I found this nice message in my mailbox:</p>
<blockquote>
<p><strong>From:</strong> Sebastian R. <…<span class="citation">@gmail.com</span>><br/><strong>To:</strong> Joachim Breitner <script type="text/javascript">
</script><noscript>joachim at cis dot upenn dot edu</noscript><br/><strong>Subject:</strong> Re: Errors</p>
<blockquote>
<p>a simple “you wrote import when it should have been import” would have been a better user of both our time.</p>
</blockquote>
<p>We're both programmers. How about I cut ALL of the unnecessary garbage and just tell you to s/import/input/ on that last quotation (the thing immediately before this paragraph, in case you didn't know).</p>
<p>I blatantly quoted the error, like this:</p>
<blockquote>
<p>In your introduction note you have written:</p>
<blockquote>
<p>n contrast to a classical intro into Haskell, we do not start with numbers, booleans, tuples, lists and strings, but we start with pictures. These are of course library-defined (hence the input CodeWorld) and not part of “the language”. But that does not make them less interesting, and in fact, even the basic boolean type is library defined – it just happens to be the standard library.</p>
</blockquote>
<p>Howeverm there is no <code>input CodeWorld</code> in the code above.</p>
</blockquote>
<p>Since that apparently wasn't clear enough, in my second email to you I had to highlight it like so:</p>
<blockquote>
<p>You might note that I quoted this precisely from the lectures... and so I repeat myself... this came from <strong>your</strong> lectures; they're not my words!</p>
<blockquote>
<p>In contrast to a classical intro into Haskell, we do not start with numbers, booleans, tuples, lists and strings, but we start with pictures. These are of course library-defined (hence the <span style="color:red">input CodeWorld</span>) and not part of “the language”. But that does not make them less interesting, and in fact, even the basic boolean type is library defined – it just happens to be the standard library.</p>
</blockquote>
<p>This time around, I've highlighted the issue. I hope that made it easier for you to spot...</p>
</blockquote>
<p>I'm not sure if you're memeing at me or not now, but it seems either your reading comprehension, or your logical deduction skills might be substandard. Unfortunately, there isn't much either of us can do about that, so I'm happy to accept that some people will be so stupid; after all, it's to be expected and if we don't accept that which is to be expected then we live our lives in denial.</p>
<p>Happy to wrap up this discusson here, Seb...</p>
<p>On Fri, Aug 4, 2017 at 12:22 AM, Joachim Breitner <script type="text/javascript">
</script><noscript>joachim at cis dot upenn dot edu</noscript> wrote:<br/>…</p>
</blockquote>
<p>Well, I chose to be amused by this, and I am sharing my amusement with you.</p>Sun, 06 Aug 2017 11:14:05 -0400How is coinduction the dual of induction?
http://www.joachim-breitner.de/blog/727-How_is_coinduction_the_dual_of_induction_
http://www.joachim-breitner.de/blog/727-How_is_coinduction_the_dual_of_induction_http://www.joachim-breitner.de/blog/727-How_is_coinduction_the_dual_of_induction_#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Earlier today, I demonstrated how to work with <a href="http://www.joachim-breitner.de/blog/726-Coinduction_in_Coq_and_Isabelle">coinduction in the theorem provers Isabelle, Coq and Agda</a>, with a very simple example. This reminded me of a discussion I had in Karlsruhe with my then colleague Denis Lohner: If coinduction is the dual of induction, why do the induction principles look so different? I like what we observed there, so I’d like to share this.</p>
<p>The following is mostly based on my naive understanding of coinduction based on what I observe in <a href="http://isabelle.in.tum.de/dist/Isabelle2016-1/doc/datatypes.pdf">the implementation in Isabelle</a>. I am sure that a different, more categorial presentation of datatypes (as initial resp. terminal objects in some category of algebras) makes the duality more obvious, but that does not necessarily help the working Isabelle user who wants to make sense of coninduction.</p>
<h3 id="inductive-lists">Inductive lists</h3>
<p>I will use the usual polymorphic list data type as an example. So on the one hand, we have normal, finite inductive lists:</p>
<pre><code>datatype 'a list = nil | cons (hd : 'a) (tl : "'a list")</code></pre>
<p>with the well-known induction principle that many of my readers know by heart (syntax slightly un-isabellized):</p>
<pre><code>P nil → (∀x xs. P xs → P (cons x xs)) → ∀ xs. P xs</code></pre>
<h3 id="coinductive-lists">Coinductive lists</h3>
<p>In contrast, if we define our lists coinductively to get possibly infinite, Haskell-style lists, by writing</p>
<pre><code>codatatype 'a llist = lnil | lcons (hd : 'a) (tl : "'a llist")</code></pre>
<p>we get the following coinduction principle:</p>
<pre><code>(∀ xs ys.
R xs ys' → (xs = lnil) = (ys = lnil) ∧
(xs ≠ lnil ⟶ ys' ≠ lnil ⟶
hd xs = hd ys ∧ R (tl xs) (tl ys))) →
→ (∀ xs ys. R xs ys → xs = ys)</code></pre>
<p>This is less scary that it looks at first. It tell you “if you give me a relation <code>R</code> between lists which implies that either both lists are empty or both lists are nonempty, and furthermore if both are non-empty, that they have the same head and tails related by <code>R</code>, then any two lists related by <code>R</code> are actually equal.”</p>
<p>If you think of the infinte list as a series of states of a computer program, then this is nothing else than a <em>bisimulation</em>.</p>
<p>So we have two proof principles, both of which make intuitive sense. But how are they related? They look very different! In one, we have a predicate <code>P</code>, in the other a relation <code>R</code>, to point out just one difference.</p>
<h3 id="relation-induction">Relation induction</h3>
<p>To see how they are dual to each other, we have to recognize that both these theorems are actually specializations of a more general (co)induction principle.</p>
<p>The <code>datatype</code> declaration automatically creates a <em>relator</em>:</p>
<pre><code>rel_list :: ('a → 'b → bool) → 'a list → 'b list → bool</code></pre>
<p>The definition of <code>rel_list R xs ys</code> is that <code>xs</code> and <code>ys</code> have the same shape (i.e. length), and that the corresponding elements are pairwise related by <code>R</code>. You might have defined this relation yourself at some time, and if so, you probably introduced it as an inductive predicate. So it is not surprising that the following induction principle characterizes this relation:</p>
<pre><code>Q nil nil →
(∀x xs y ys. R x y → Q xs ys → Q (cons x xs) (cons y ys)) →
(∀xs ys → rel_list R xs ys → Q xs ys)</code></pre>
<p>Note how how similar this lemma is in shape to the normal induction for lists above! And indeed, if we choose <code>Q xs ys ↔ (P xs ∧ xs = ys)</code> and <code>R x y ↔ (x = y)</code>, then we obtain exactly that. In that sense, the relation induction is a generalization of the normal induction.</p>
<h3 id="relation-coinduction">Relation coinduction</h3>
<p>The same observation can be made in the coinductive world. Here, as well, the <code>codatatype</code> declaration introduces a function</p>
<pre><code>rel_llist :: ('a → 'b → bool) → 'a llist → 'b llist → bool</code></pre>
<p>which relates lists of the same shape with related elements – only that this one also relates infinite lists, and therefore is a coinductive relation. The corresponding rule for proof by coinduction is not surprising and should remind you of bisimulation, too:</p>
<pre><code>(∀xs ys.
R xs ys → (xs = lnil) = (ys = lnil) ∧
(xs ≠ lnil ⟶ ys ≠ lnil ⟶
Q (hd xs) (hd ys) ∧ R (tl xs) (tl ys))) →
(∀ xs ys → R xs ys → rel_llist Q xs ys)</code></pre>
<p>It is even more obvious that this is a generalization of the standard coinduction principle shown above: Just instantiate <code>Q</code> with equality, which turns <code>rel_llist Q</code> into equality on the lists, and you have the theorem above.</p>
<h3 id="the-duality">The duality</h3>
<p>With our induction and coinduction principle generalized to relations, suddenly a duality emerges: If you turn around the implication in the conclusion of one you get the conclusion of the other one. This is an example of “co<em>something</em> is <em>something</em> with arrows reversed”.</p>
<p>But what about the premise(s) of the rules? What happens if we turn around the arrow here? Although slighty less immediate, it turns out that they are the same as well. To see that, we start with the premise of the coinduction rule, reverse the implication and then show that to be equivalent to the two premises of the induction rule:</p>
<pre><code>(∀xs ys.
R xs ys ← (xs = lnil) = (ys = lnil) ∧
(xs ≠ lnil ⟶ ys ≠ lnil ⟶
Q (hd xs) (hd ys) ∧ R (tl xs) (tl ys)))
= { case analysis (the other two cases are vacuously true) }
(∀xs ys.
xs = lnil → ys = lnil →
R xs ys ← (xs = lnil) = (ys = lnil) ∧
(xs ≠ lnil ⟶ ys ≠ lnil ⟶
Q (hd xs) (hd ys) ∧ R (tl xs) (tl ys)))
∧ (∀xs ys.
xs ≠ lnil ⟶ ys ≠ lnil
R xs ys ← (xs = lnil) = (ys = lnil) ∧
(xs ≠ lnil ⟶ ys ≠ lnil ⟶
Q (hd xs) (hd ys) ∧ R (tl xs) (tl ys)))
= { simplification }
(∀xs ys. xs = lnil → ys = lnil → R xs ys
∧ (∀x xs y ys. R (cons x xs) (cons y ys) ← (Q x y ∧ R xs ys))
= { more rewriting }
R nil nil
∧ (∀x xs y ys. Q x y → R xs ys → R (cons x xs) (cons y ys))</code></pre>
<h3 id="conclusion">Conclusion</h3>
<p>The coinduction rule is not the direct dual of the induction rule, but both are specializations of more general, relational proof methods, where the duality is clearly present.</p>
<p>More generally, this little excursion shows that it is often beneficial to think of types less as sets, and more as relations – this way of thinking is surprisingly fruitful, and led to proofs of <a href="https://en.wikipedia.org/wiki/Parametricity">parametricity</a> and free theorems and other nice things.</p>Thu, 27 Jul 2017 22:05:32 -0400Coinduction in Coq and Isabelle
http://www.joachim-breitner.de/blog/726-Coinduction_in_Coq_and_Isabelle
http://www.joachim-breitner.de/blog/726-Coinduction_in_Coq_and_Isabellehttp://www.joachim-breitner.de/blog/726-Coinduction_in_Coq_and_Isabelle#commentsmail@joachim-breitner.de (Joachim Breitner)<p>The <a href="http://deepspec.org/event/dsss17/">DeepSpec Summer School</a> is almost over, and I have had a few good discussions. One revolved around coinduction: What is it, how does it differ from induction, and how do you actually prove something. In the course of the discussion, I came up with a very simple coinductive exercise, and solved it both in Coq and Isabelle</p>
<h3 id="the-task">The task</h3>
<p>Define the extended natural numbers coinductively. Define the <span class="math">min</span> function and the <span class="math"> ≤ </span> relation. Show that <span class="math">min(<em>n</em>, <em>m</em>) ≤ <em>n</em></span> holds.</p>
<h3 id="coq">Coq</h3>
<p>The definitions are straight forward. Note that in Coq, we use the same command to define a coinductive data type and a coinductively defined relation:</p>
<pre class="coq"><code>CoInductive ENat :=
| N : ENat
| S : ENat -> ENat.
CoFixpoint min (n : ENat) (m : ENat)
:=match n, m with | S n', S m' => S (min n' m')
| _, _ => N end.
CoInductive le : ENat -> ENat -> Prop :=
| leN : forall m, le N m
| leS : forall n m, le n m -> le (S n) (S m).</code></pre>
<p>The lemma is specified as</p>
<pre class="coq"><code>Lemma min_le: forall n m, le (min n m) n.</code></pre>
<p>and the proof method of choice to show that some coinductive relation holds, is <code>cofix</code>. One would wish that the following proof would work:</p>
<pre class="coq"><code>Lemma min_le: forall n m, le (min n m) n.
Proof.
cofix.
destruct n, m.
* apply leN.
* apply leN.
* apply leN.
* apply leS.
apply min_le.
Qed.</code></pre>
<p>but we get the error message</p>
<pre><code>Error:
In environment
min_le : forall n m : ENat, le (min n m) n
Unable to unify "le N ?M170" with "le (min N N) N</code></pre>
<p>Effectively, as Coq is trying to figure out whether our proof is correct, i.e. type-checks, it stumbled on the equation <code>min N N = N</code>, and like a kid scared of coinduction, it did not dare to “run” the <code>min</code> function. The reason it does not just “run” a <code>CoFixpoint</code> is that doing so too daringly might simply not terminate. So, as <a href="http://adam.chlipala.net/cpdt/html/Coinductive.html">Adam explains in a chapter of his book</a>, Coq reduces a cofixpoint <em>only</em> when it is the scrutinee of a <code>match</code> statement.</p>
<p>So we need to get a <code>match</code> statement in place. We can do so with a helper function:</p>
<pre class="coq"><code>Definition evalN (n : ENat) :=
match n with | N => N
| S n => S n end.
Lemma evalN_eq : forall n, evalN n = n.
Proof. intros. destruct n; reflexivity. Qed.</code></pre>
<p>This function does not really do anything besides nudging Coq to actually evaluate its argument to a constructor (<code>N</code> or <code>S _</code>). We can use it in the proof to guide Coq, and the following goes through:</p>
<pre class="coq"><code>Lemma min_le: forall n m, le (min n m) n.
Proof.
cofix.
destruct n, m; rewrite <- evalN_eq with (n := min _ _).
* apply leN.
* apply leN.
* apply leN.
* apply leS.
apply min_le.
Qed.</code></pre>
<h3 id="isabelle">Isabelle</h3>
<p>In Isabelle, definitions and types are very different things, so we use different commands to define <code>ENat</code> and <code>le</code>:</p>
<pre class="isabelle"><code>theory ENat imports Main begin
codatatype ENat = N | S ENat
primcorec min where
"min n m = (case n of
N ⇒ N
| S n' ⇒ (case m of
N ⇒ N
| S m' ⇒ S (min n' m')))"
coinductive le where
leN: "le N m"
| leS: "le n m ⟹ le (S n) (S m)"</code></pre>
<p>There are actually many ways of defining <code>min</code>; I chose the one most similar to the one above. For more details, see the <a href="http://isabelle.in.tum.de/dist/Isabelle2016-1/doc/corec.pdf"><code>corec</code> tutorial</a>.</p>
<p>Now to the proof:</p>
<pre class="isabelle"><code>lemma min_le: "le (min n m) n"
proof (coinduction arbitrary: n m)
case le
show ?case
proof(cases n)
case N then show ?thesis by simp
next
case (S n') then show ?thesis
proof(cases m)
case N then show ?thesis by simp
next
case (S m') with ‹n = _› show ?thesis
unfolding min.code[where n = n and m = m]
by auto
qed
qed
qed</code></pre>
<p>The <code>coinduction</code> proof methods produces this goal:</p>
<pre><code>proof (state)
goal (1 subgoal):
1. ⋀n m. (∃m'. min n m = N ∧ n = m') ∨
(∃n' m'.
min n m = S n' ∧
n = S m' ∧
((∃n m. n' = min n m ∧ m' = n) ∨ le n' m'))</code></pre>
<p>I chose to spell the proof out in the Isar proof language, where the outermost proof structure is done relatively explicity, and I proceed by case analysis mimiking the <code>min</code> function definition.</p>
<p>In the cases where one argument of <code>min</code> is <code>N</code>, Isabelle’s <em>simplifier</em> (a term rewriting tactic, so to say), can solve the goal automatically. This is because the <code>primcorec</code> command produces a bunch of lemmas, one of which states <code>n = N ∨ m = N ⟹ min n m = N</code>.</p>
<p>In the other case, we need to help Isabelle a bit to reduce the call to <code>min (S n) (S m)</code> using the <code>unfolding</code> methods, where <code>min.code</code> contains exactly the equation that we used to specify <code>min</code>. Using just <code>unfolding min.code</code> would send this method into a loop, so we restrict it to the concrete arguments <code>n</code> and <code>m</code>. Then <code>auto</code> can solve the remaining goal (despite all the existential quantifiers).</p>
<h3 id="summary">Summary</h3>
<p>Both theorem provers are able to prove the desired result. To me it seems that it is slightly more convenient in Isabelle because a lot of Coq infrastructure relies on the type checker being able to effectively evaluate expressions, which is tricky with cofixpoints, wheras <em>evaluation</em> plays a much less central role in Isabelle, where <em>rewriting</em> is the crucial technique, and while one still cannot simply throw <code>min.code</code> into the simpset, so working with objects that do not evaluate easily or completely is less strange.</p>
<h3 id="agda">Agda</h3>
<p>I was challenged to do it in Agda. Here it is:</p>
<pre class="agda"><code>module ENat where
open import Coinduction
data ENat : Set where
N : ENat
S : ∞ ENat → ENat
min : ENat → ENat → ENat
min (S n') (S m') = S (♯ (min (♭ n') (♭ m')))
min _ _ = N
data le : ENat → ENat → Set where
leN : ∀ {m} → le N m
leS : ∀ {n m} → ∞ (le (♭ n) (♭ m)) → le (S n) (S m)
min_le : ∀ {n m} → le (min n m) n
min_le {S n'} {S m'} = leS (♯ min_le)
min_le {N} {S m'} = leN
min_le {S n'} {N} = leN
min_le {N} {N} = leN</code></pre>
<p>I will refrain from commenting it, because I do not really know what I have been doing here, but it typechecks, and refer you to the <a href="http://agda.readthedocs.io/en/latest/language/coinduction.html">official documentation on coinduction in Agda</a>. But let me note that I wrote this using plain inductive types and recursion, and added <code>∞</code>, <code>♯</code> and <code>♭</code> until it worked.</p>Thu, 27 Jul 2017 16:24:03 -0400The Micro Two Body Problem
http://www.joachim-breitner.de/blog/725-The_Micro_Two_Body_Problem
http://www.joachim-breitner.de/blog/725-The_Micro_Two_Body_Problemhttp://www.joachim-breitner.de/blog/725-The_Micro_Two_Body_Problem#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Inspired by recent <a href="http://phdcomics.com/comics/archive.php?comicid=1961">PhD comic “Academic Travel”</a> and not-so-recent <a href="https://xkcd.com/657">xkcd comic “Movie Narrative Charts”</a>, I created the following graphics, which visualizes the travels of an academic couple over the course of 10 months (place names anonymized).</p>
<div class="figure">
<img src="//www.joachim-breitner.de/various/reiseplot-anonym.svg" alt="Two bodies traveling the world"/><p class="caption">Two bodies traveling the world</p>
</div>Thu, 06 Jul 2017 16:27:46 +0100Bundestag beschließt Ehe für alle
http://www.joachim-breitner.de/blog/724-Bundestag_beschlie%C3%9Ft_Ehe_f%C3%BCr_alle
http://www.joachim-breitner.de/blog/724-Bundestag_beschlie%C3%9Ft_Ehe_f%C3%BCr_allehttp://www.joachim-breitner.de/blog/724-Bundestag_beschlie%C3%9Ft_Ehe_f%C3%BCr_alle#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Nach Jahrzehnten des Mauerns und des Blockierens der konservativen Parteien im Bundestag ging plötzlich alles ganz schnell. Auslöser war ein Besuch der Bundeskanzlerin Fräulein Merkel bei Ihrem Amtskollegen Donald Trump. Der Immobilienmogul lebt, sozusagen als Paradebeispiel für den gesellschaftlichen Fortschritt in seinem Land, in einer Ehe mit einer Frau (sogar einer Ausländerin!) lebt. Merkel erzählte danach im Interview mit dem Playboy:</p>
<blockquote>
<p>Ich war sehr überrascht und zutiefst bewegt, mitzuerleben, wie fürsorglich, innig und vertraulich die Ehemänner, Verzeihung, Eheleute Trump miteinander umgehen. Und sie sind in den USA damit nicht alleine!</p>
<p>Daher muss ich eingestehen dass ich mir unsicher geworden bin, ob meine Überzeugung in Deutschland noch mehrheitsfähig ist. Ich könnte mir vorstellen, dazu einmal den Bundestag zu befragen – natürlich als Gewissensentscheidung und ohne Fraktionszwang.</p>
</blockquote>
<p>Der Koaliationspartner SPD griff diesen Vorschlag umgehend auf und brachte ein „Ehe-für-Alle“ Gesetz auf den Weg, das im entsprechenden Paragrafen des Bürgerlichen Gesetzbuchs den Passus „Die Ehe wird zwischen zwei <em>Männern</em> auf Lebenszeit geschlossen.“ durch „Die Ehe wird zwischen zwei <em>Menschen</em> auf Lebenszeit geschlossen.“ Der Rest ist Geschichte: Mit den Stimmen der Grünen, der Linkspartei und einiger Abgeordneter der Union (darunter etliche verheiratete Männer!) stimmten dafür. In nur wenigen Monaten können Adam und Eva Müller also im Standesamt den Bund der Ehe eingehen – als wären sie Adam und Stefan Müller.</p>
<p>Besonders ausgiebig feierten die Grünen, die seit ihrer Gründung in den 80ern fanatisch auf diesen Moment hingearbeitet haben. Unvergessen wie Ströbele Anfang der 90er mit einer Dame auf dem Bundespresseball erschien und sie als seine Ehefrau Monika vorstellte (offiziell wohnte sie als Gärtnerin bei ihm). Ebenso unvergessen der März 1996, als die Herren der Grünenfraktion die Abgeordneten der anderen Parteien zu Steak und Pommes einluden und erst hinterher verrieten, dass die Speise tatsächlich und ausschließlich von Frauen zubereitet wurden. Seit dem waren Restaurants mit Unisex-Speisekarten und gemeinsamer Küche im progressiven Berlin immer häufiger anzutreffen.</p>
<p>Frau Gerhard-Ecking (bürgerlich natürlich Fräulein Ecking), Fraktionssprecherin der Grünen, kommentiert den Bundestagsbeschluss:</p>
<blockquote>
<p>Frauen dürfen wählen, dürfen als Soldaten dienen. Frauen leiten heutzutage DAX-Konzerne und sogar Samengroßbanken. Es ist unverständlich warum Ihnen trotz dem nicht zugetraut wird, einem Ehemann zu lieben, zu umsorgen, zu unterstützen, mit ihm alt zu werden und sich gegenseitig im Alter abzusichern. Dabei geht es den meisten Ehemännern ja gar nicht darum um diese hohen Werte der Ehe, sie haben es lediglich auf den Steuervorteil abgesehen haben! Endlich also auch Ehemännersplitting für Frauen!</p>
</blockquote>
<p>Während Ihrer Rede stand, wie so oft, das bekannte Photomodel Herr Gerhard, hinter ihr und entzückte die Reporter mit einem grau-mellierten Zweiteiler und amüsanter Blümlichenkrawatte. Es heißt, sie hätten gemeinsam ein Kleintierzuchtverein gegründet, um wenigstens bei der Bank ein gemeinsames Konto eröffnen zu könne.</p>
<p>Vehemente Kritik kam wie erwartet von Seiten der katholischen Kirche. Die Doppelspitze der Deutschen Bischofskonferenz, Ehemänner Kardinale Jonas und Hannes Meissner-Stolz, verkündeten in einer Presseerklärung:</p>
<blockquote>
<p>Heute ist ein schwarzer Tag für die Christen in der Bundesrepublik. Das heilige Sakrament der Ehe, von Jesus zwölf mal gestiftet, lässt sich nicht per Abstimmung auf Frauen übertragen. Jesus zog mit Jüngern durch das Land, nicht mit Jüngerinnen, und genau so ist Gottes Wille zu verstehen. Frauen und Männer sind von Natur aus zu verschieden. Wenn jetzt noch mehr Männer in Deutschland in so gottloser Weise das Haus und das Bett mit Frauen teilen, wird die Gesellschaft daran zugrunde gehen.</p>
<p>Die Kirche kann Mitglieder, die eine solche „Bundestagsehe“ mit einer Frau eingehen, nicht mehr in ihren Reihen aufnehmen können.</p>
</blockquote>
<p>Die Börsen reagierten verhalten. Lediglich die Aktien der Vereinigten Samenbanken notierten mit deutlichen Verlusten. Analysten vermuten dass sich die Gesetzeslage bezüglich Direktzeugung – bisher illegal aber nicht strafbar – in Kürze entsprechend anpasst und dann weniger Frauen die Dienste der Banken in Anspruch nehmen werden.</p>
<p>Fräulein Merkel, die selbst gegen den Gesetzesvorschlag votierte, kommentierte dass sie auch weiterhin an traditionellen, christlichen Werten festhalten wird, und eine Ehe für sie nicht daher in Frage kommt.</p>Sun, 02 Jul 2017 15:43:48 -0400The perils of live demonstrations
http://www.joachim-breitner.de/blog/723-The_perils_of_live_demonstrations
http://www.joachim-breitner.de/blog/723-The_perils_of_live_demonstrationshttp://www.joachim-breitner.de/blog/723-The_perils_of_live_demonstrations#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Yesterday, I was giving a <a href="https://www.meetup.com/de-DE/haskellhackers/events/240759486/">talk at the The South SF Bay Haskell User Group</a> about how implementing lock-step simulation is trivial in Haskell and how Chris Smith and me are using this to make <a href="https://code.world/">CodeWorld</a> even more attractive to students. I gave the talk before, at <a href="http://www.composeconference.org/2017/program/">Compose::Conference</a> in New York City earlier this year, so I felt well prepared. On the flight to the West Coast I slightly extended the slides, and as I was too cheap to buy in-flight WiFi, I tested them only locally.</p>
<p>So I arrived at the offices of Target<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a> in Sunnyvale, got on the WiFi, uploaded my slides, which are in fact one large interactive CodeWorld program, and tried to run it. But I got a type error…</p>
<p>Turns out that the API of CodeWorld was changed <a href="https://github.com/google/codeworld/commit/054c811b494746ec7304c3d495675046727ab114">just the day before</a>:</p>
<pre><code>commit 054c811b494746ec7304c3d495675046727ab114
Author: Chris Smith <cdsmith@gmail.com>
Date: Wed Jun 21 23:53:53 2017 +0000
Change dilated to take one parameter.
Function is nearly unused, so I'm not concerned about breakage.
This new version better aligns with standard educational usage,
in which "dilation" means uniform scaling. Taken as a separate
operation, it commutes with rotation, and preserves similarity
of shapes, neither of which is true of scaling in general.</code></pre>
<p>Ok, that was <a href="https://github.com/nomeata/codeworld-talk/commit/9a5830b0a20010a9e54ab23a6f4aeafd31fccc6b">quick to fix</a>, and the CodeWorld server started to compile my code, and compiled, and aborted. It turned out that my program, presumably the larges CodeWorld interaction out there, hit the time limit of the compiler.</p>
<p>Luckily, Chris Smith just arrived at the venue, and he emergency-bumped the compiler time limit. The program compiled and I could start my presentation.</p>
<p>Unfortunately, the biggest blunder was still awaiting for me. I came to the slide where two instances of pong are played over a simulated network, and my point was that the two instances are perfectly in sync. Unfortunately, they were not. I guess it did support my point that lock-step simulation can easily go wrong, but it really left me out in the rain there, and I could not explain it – I did not modify this code since New York, and there it worked flawless<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a>. In the end, I could save my face a bit by running the <a href="https://code.world/run.html?mode=haskell&dhash=DoE66gidx7VusA3qcMRI_hg">real pong game</a> against an attendee over the network, and no desynchronisation could be observed there.</p>
<p>Today I dug into it and it took me a while, and it turned out that the problem was not in CodeWorld, or the lock-step simulation code discussed in <a href="https://arxiv.org/abs/1705.09704">our paper about it</a>, but in the code in my presentation that simulated the delayed network messages; in some instances it would deliver the UI events in different order to the two simulated players, and hence cause them do something different. Phew.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn1"><p>Yes, the retail giant. Turns out that they have a small but enthusiastic Haskell-using group in their IT department.<a href="#fnref1">↩</a></p></li>
<li id="fn2"><p>I hope the video is going to be online soon, then you can check for yourself.<a href="#fnref2">↩</a></p></li>
</ol>
</div>Fri, 23 Jun 2017 16:54:36 -0700Farewall green cap
http://www.joachim-breitner.de/blog/722-Farewall_green_cap
http://www.joachim-breitner.de/blog/722-Farewall_green_caphttp://www.joachim-breitner.de/blog/722-Farewall_green_cap#commentsmail@joachim-breitner.de (Joachim Breitner)<p>For the last two years, I was known among swing dancers for my green flat cap:</p>
<div class="figure">
<img src="//www.joachim-breitner.de/bilder/scales/20160526153528_full.jpg" alt="Monti, a better model than me"/><p class="caption">Monti, a better model than me</p>
</div>
<p>This cap was very special: It was a gift from a good friend who sewed it by hand from what used to be a table cloth of my deceased granny, and it has traveled with me to many corners of the world.</p>
<p>Just like last week, when I was in Paris where I attended the Charleston class of Romuald and Laura on Saturday (April 29). The following Tuesday I went to a Swing Social and wanted to put on the hat, and noticed that it was gone. The next day I bugged the manager and the caretaker of the venue of the class (Salles Sainte-Roche), and it seems that the hat was still there, that morning, im Salle Kurtz<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a>, but when I went there it was gone.</p>
<p>And that is sad.</p>
<div class="figure">
<img src="//www.joachim-breitner.de/bilder/scales/20170426215737_full.jpg" alt="The last picture with the hat"/><p class="caption">The last picture with the hat</p>
</div>
<div class="footnotes">
<hr/>
<ol>
<li id="fn1"><p>How fitting, given that my granny’s maiden name is Kurz.<a href="#fnref1">↩</a></p></li>
</ol>
</div>Fri, 05 May 2017 18:13:40 -0400Mütze Ade
http://www.joachim-breitner.de/blog/721-M%C3%BCtze_Ade
http://www.joachim-breitner.de/blog/721-M%C3%BCtze_Adehttp://www.joachim-breitner.de/blog/721-M%C3%BCtze_Ade#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Seit wohl etwa zwei Jahren ist eine grüne Mütze mein Markenzeichen beim Swing-Tanzen:</p>
<div class="figure">
<img src="//www.joachim-breitner.de/bilder/scales/20160526153528_full.jpg" alt="Monti, das bessere Model"/><p class="caption">Monti, das bessere Model</p>
</div>
<p>Diese Mütze war etwas besonderes, denn sie war ein Geschenk von einer guten Freundin, handgenäht aus einem Tischtuchstoff meiner verstorbenen Oma, und reiste mit mir schon in viele Ecken der Welt.</p>
<p>So auch letzte Woche nach Paris, wo ich am Samstag bei Romuald und Laura einen Charleston-Kurs besuchte – und als ich dann am Dienstag beim Social in Le Chalet du Parc die Mütze aufziehen wollte, war sie nicht mehr da. Ich habe zwar noch den Verwalter und den Hausmeister der Salles Saite-Roche, dem Veranstaltungsort des Kurses, aufgescheucht, und die Mütze wurde wohl noch am Vormittag im Salle Kurtz<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a> gesehen, aber ich war zu spät und die Mütze ist nun weg.</p>
<p>Und das ist schade.</p>
<div class="figure">
<img src="//www.joachim-breitner.de/bilder/scales/20170426215737_full.jpg" alt="Das letzte Bild mit Mütze"/><p class="caption">Das letzte Bild mit Mütze</p>
</div>
<div class="footnotes">
<hr/>
<ol>
<li id="fn1"><p>Wie passend, meine Oma ist eine geborene Kurz.<a href="#fnref1">↩</a></p></li>
</ol>
</div>Thu, 04 May 2017 17:44:10 -0400ghc-proofs rules more now
http://www.joachim-breitner.de/blog/720-ghc-proofs_rules_more_now
http://www.joachim-breitner.de/blog/720-ghc-proofs_rules_more_nowhttp://www.joachim-breitner.de/blog/720-ghc-proofs_rules_more_now#commentsmail@joachim-breitner.de (Joachim Breitner)<p>A few weeks ago I blogged about an experiment of mine, where I <a href="/blog/717-Why_prove_programs_equivalent_when_your_compiler_can_do_that_for_you_.html.en">proved equalities of Haskell programs by (ab)using the GHC simplifier</a>. For more details, please see that post, or the <a href="https://www.youtube.com/watch?v=jcL4bp4FMUw&feature=youtu.be">video of my talk at the Zürich Haskell User Group</a>, but one reason why this approach has any chance of being useful is the compiler’s support for rewrite rules.</p>
<p>Rewrite rules are program equations that the programmer specifies in the source file, and which the compiler then applies, from left to right, whenever some intermediate code matches the left-hand side of the equation. One such rule, for example, is</p>
<pre><code>{-# RULES "foldr/nil" forall k z. foldr k z [] = z #-}</code></pre>
<p>taken right out of the standard library.</p>
<p>In my blog post I went through the algebraic laws that a small library of mine, <a href="http://hackage.haskell.org/package/successors-0.1/docs/Control-Applicative-Successors.html">successors</a>, should fulfill, and sure enough, once I got to more interesting proofs, they would not go through just like that. At that point I had to add additional rules to the file I was editing, which helped the compiler to finish the proofs. Some of these rules were simple like</p>
<pre><code>{-# RULES "mapFB/id" forall c. mapFB c (\x -> x) = c #-}
{-# RULES "foldr/nil" forall k n. GHC.Base.foldr k n [] = n #-}
{-# RULES "foldr/undo" forall xs. GHC.Base.foldr (:) [] xs = xs #-}</code></pre>
<p>and some are more intricate like</p>
<pre><code>{-# RULES "foldr/mapFB" forall c f g n1 n2 xs.
GHC.Base.foldr (mapFB c f) n1 (GHC.Base.foldr (mapFB (:) g) n2 xs)
= GHC.Base.foldr (mapFB c (f.g)) (GHC.Base.foldr (mapFB c f) n1 n2) xs
#-}</code></pre>
<p>But there is something fishy going on here: The <code>foldr/nil</code> rule is identical to a rule in the standard library! I should not have to add to my file that as I am proving things. So I knew that the GHC plugin, which I wrote to do these proofs, was doing something wrong, but I did not investigate for a while.</p>
<p>I returned to this problem recetly, and with the efficient and quick <a href="https://ghc.haskell.org/trac/ghc/ticket/13614">help of Simon Peyton Jones</a>, I learned what I was doing wrong.<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a> After fixing it, I could remove all the simple rules from the files with my proofs. And to my surprise, I could remove the intricate rule as well!</p>
<p>So with this bug fixed, ghc-proofs is able to prove <em>all</em> the Functor, Applicative and Monad rules of the Succs functor <a href="https://github.com/nomeata/ghc-proofs/blob/ea17e78a98c20995b2de4f64a9eb4e299f6dcde4/examples/Successors.hs">without any additional rewrite rules</a>, as you can see in the example file! (I still have to strategically place <code>seq</code>s in a few places.)</p>
<p>That’s great, isn’t it! Yeah, sure. But having to introduce the rules at that point provided a very good narrative in my talk, so when I will give a similar talk next week in Pairs (actually, twice, first <a href="https://www.irif.fr/gt/acs/index">at the university</a> and then <a href="https://www.meetup.com/de-DE/haskell-paris/events/239389804/">at the Paris Haskell meetup</a>, I will have to come up with a different example that calls for additional rewrite rules.</p>
<p>In related news: Since the last blog post, ghc-proofs learned to interpret proof specifications like</p>
<pre><code>applicative_law4 :: Succs (a -> b) -> a -> Proof
applicative_law4 u y = u <*> pure y
=== pure ($ y) <*> u</code></pre>
<p>where it previously only understood</p>
<pre><code>applicative_law4 = (\ u (y::a) -> u <*> (pure y :: Succs a))
=== (\ u (y::a) -> pure ($ y) <*> u)
</code></pre>
<p>I am not sur if this should be uploaded to Hackage, but I invite you to play around with the <a href="https://github.com/nomeata/ghc-proofs">GitHub version of ghc-proofs</a>.</p>
<div class="footnotes">
<hr/>
<ol>
<li id="fn1"><p>In short: I did not initialize the simplifier with the right <code>InScopeSet</code>, so RULES about functions defined in the current module were not always applied, and I did not feed the <code>eps_rules</code> to the simplifier, which contains all the rules found in imported packages, such as <code>base</code>.<a href="#fnref1">↩</a></p></li>
</ol>
</div>Thu, 27 Apr 2017 23:11:38 -0400veggies: Haskell code generation from scratch
http://www.joachim-breitner.de/blog/719-veggies__Haskell_code_generation_from_scratch
http://www.joachim-breitner.de/blog/719-veggies__Haskell_code_generation_from_scratchhttp://www.joachim-breitner.de/blog/719-veggies__Haskell_code_generation_from_scratch#commentsmail@joachim-breitner.de (Joachim Breitner)<p>How hard it is to write a compiler for Haskell Core? Not too hard, actually!</p>
<p>I wish we had a formally verified compiler for Haskell, or at least for GHC’s intermediate language Core. Now formalizing that part of GHC itself seems to be far out of reach, with the many phases the code goes through (Core to STG to CMM to Assembly or LLVM) and optimizations happening at all of these phases and the many complicated details to the highly tuned GHC runtime (pointer tagging, support for concurrency and garbage collection).</p>
<h3 id="introducing-veggies">Introducing Veggies</h3>
<p>So to make that goal of a formally verified compiler more feasible, I set out and implemented code generation from GHC’s intermediate language Core to LLVM IR, with simplicity as the main design driving factor.</p>
<p>You can find the result in the <a href="https://github.com/nomeata/veggies">GitHub repository of <strong>veggies</strong></a> (the name derives from “verifiable GHC”). If you clone that and run <code>./boot.sh some-directory</code>, you will find that you can use the program <code>some-directory/bin/veggies</code> just like like you would use <code>ghc</code>. It comes with the full <code>base</code> library, so your favorite variant of HelloWorld might just compile and run.</p>
<p>As of now, the code generation handles all the Core constructs (which is easy when you simply ignore all the types). It supports a good number of primitive operations, including pointers and arrays – I implement these as need – and has support for FFI calls into C.</p>
<h3 id="why-you-dont-want-to-use-veggies">Why you don't want to use Veggies</h3>
<p>Since the code generator was written with simplicity in mind, performance of the resulting code is abysmal: Everything is boxed, i.e. represented as pointer to some heap-allocated data, including “unboxed” integer values and “unboxed” tuples. This is very uniform and simplifies the code, but it is also slow, and because there is no garbage collection (and probably never will be for this project), will fill up your memory quickly.</p>
<p>Also, the code is currently only supports 64bit architectures, and this is hard-coded in many places.</p>
<p>There is no support for concurrency.</p>
<h3 id="why-it-might-be-interesting-to-you-nevertheless">Why it might be interesting to you nevertheless</h3>
<p>So if it is not really usable to run programs with, should you care about it? Probably not, but maybe you do for one of these reasons:</p>
<ul>
<li>You always wondered how a compiler for Haskell actually works, and reading through a little over a thousands lines of code is less daunting than reading through the 34k lines of code that is GHC’s backend.</li>
<li>You have wacky ideas about Code generation for Haskell that you want to experiment with.</li>
<li>You have wacky ideas about Haskell that require special support in the backend, and want to prototype that.</li>
<li>You want to see how I use the GHC API to provide a <code>ghc</code>-like experience. (I copied GHC’s <code>Main.hs</code> and inserted a few hooks, an approach I copied from GHCJS).</li>
<li>You want to learn about running Haskell programs efficiently, and starting from veggies, you can implement all the trick of the trade yourself and enjoy observing the speed-ups you get.</li>
<li>You want to compile Haskell code to some weird platform that is supported by LLVM, but where you for some reason cannot run GHC’s runtime. (Because there are no threads and no garbage collection, the code generated by veggies does not require a runtime system.)</li>
<li>You want to formally verify Haskell code generation. Note that the code generator targets the same AST for LLVM IR that the <a href="https://github.com/vellvm/vellvm2/blob/master/src/coq/Ollvm_ast.v">vellvm2</a> project uses, so eventually, veggies can become a verified arrow in the top right corner <a href="https://deepspec.org/page/Research/">map of the DeepSpec project</a>.</li>
</ul>
<p>So feel free to play around with veggies, and report any issues you have on the GitHub repository.</p>Fri, 21 Apr 2017 11:30:27 -0400Birthday greetings communication behaviour
http://www.joachim-breitner.de/blog/718-Birthday_greetings_communication_behaviour
http://www.joachim-breitner.de/blog/718-Birthday_greetings_communication_behaviourhttp://www.joachim-breitner.de/blog/718-Birthday_greetings_communication_behaviour#commentsmail@joachim-breitner.de (Joachim Breitner)<p>Randall Munroe recently mapped <a href="https://xkcd.com/1810/">how he communicated with his social circle</a>. As I got older recently, I had an opportunity to create a similar statistics that shows how people close to me chose to fulfil their social obligations (given the current geographic circumstances):</p>
<div class="figure">
<img src="//www.joachim-breitner.de/various/birthdaydiagram.png" alt="Communication variants"/><p class="caption">Communication variants</p>
</div>
<p>(Diagram created with the <a href="https://github.com/ipython/xkcd-font">xkcd-font</a> and using <a href="http://tex.stackexchange.com/a/135408/15107">these</a> <a href="http://tex.stackexchange.com/a/74881/15107">two</a> stackoverflow answers.)</p>
<p>In related news: Heating 3½ US cups of water to a boil takes 7 minutes and 40 seconds on one particular gas stove, but only 3 minutes and 50 seconds with an electric kettle, despite the 110V-induced limitation to 1.5kW.</p>
<p>(Diagram updated on March 30, as the actual mail is slower than the other channels.)</p>Tue, 28 Mar 2017 13:42:34 -0400