<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>A Series on Ltac</title>
    <link>https://soap.coffee/~lthms/series/Ltac.html</link>
    <description>Articles in the series "A Series on Ltac"</description>
    <atom:link href="https://soap.coffee/~lthms/series/Ltac.xml" rel="self"
               type="application/rss+xml" />
    
    
    <item>
      <title>Mixing Ltac and Gallina for Fun and Profit</title>
      <link>https://soap.coffee/~lthms/posts/MixingLtacAndGallina.html</link>
      <guid>https://soap.coffee/~lthms/posts/MixingLtacAndGallina.html</guid>
      <pubDate>July 26, 2020</pubDate>
      <description>
        
        &lt;h1&gt;Mixing Ltac and Gallina for Fun and Profit&lt;/h1&gt;&lt;div id=&quot;tags-list&quot;&gt;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#tag&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&amp;nbsp;&lt;a href=&quot;/~lthms/tags/coq.html&quot; class=&quot;tag hover-periwinkle&quot; marked=&quot;&quot;&gt;coq&lt;/a&gt; &lt;/div&gt;
&lt;p&gt;One of the most misleading introductions to Coq is to say that “Gallina is
for programs, while tactics are for proofs.”  Indeed, in Coq we construct
terms of given types, always. Terms encodes both programs and proofs about
these programs. Gallina is the preferred way to construct programs, and
tactics are the preferred way to construct proofs.&lt;/p&gt;
&lt;p&gt;The key word here is “preferred.” We do not always need to use tactics to
construct a proof term. Conversely, there are some occasions where
constructing a program with tactics become handy. Furthermore, Coq actually
allows for &lt;em&gt;mixing together&lt;/em&gt; Ltac and Gallina.&lt;/p&gt;
&lt;p&gt;In the &lt;a href=&quot;/~lthms/posts/LtacPatternMatching.html&quot; class=&quot;hover-peach&quot; marked=&quot;&quot;&gt;previous article of this series&lt;/a&gt;, we
discuss how Ltac provides two very interesting features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;With &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; goal &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;&lt;/code&gt; it can inspect its context&lt;/li&gt;
&lt;li&gt;With &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; type of &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;&lt;/code&gt; it can pattern matches on types&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It turns out these features are more than handy when it comes to
metaprogramming (that is, the generation of programs by programs).&lt;/p&gt;
&lt;h2&gt;A Tale of Two Worlds, and Some Bridges&lt;/h2&gt;
&lt;p&gt;Constructing terms proofs directly in Gallina often happens when one is
writing dependently typed definition. For instance, we can write a type-safe
&lt;code class=&quot;hljs language-coq&quot;&gt;from_option&lt;/code&gt; function (inspired by &lt;a href=&quot;https://plv.csail.mit.edu/blog/unwrapping-options.html&quot; class=&quot;hover-periwinkle&quot; marked=&quot;&quot;&gt;this very nice
write-up&amp;nbsp;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#external-link&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&lt;/a&gt;) such that
the option to unwrap shall be accompanied by a proof that said option contains
something. This extra argument is used in the &lt;code class=&quot;hljs language-coq&quot;&gt;None&lt;/code&gt; case to derive a
proof of &lt;code class=&quot;hljs language-coq&quot;&gt;False&lt;/code&gt;, from which we can derive
anything.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Definition&lt;/span&gt; is_some {α} (x : option α) : bool :=
  &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; x &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt; Some &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; =&amp;gt; true | &lt;span class=&quot;hljs-type&quot;&gt;None&lt;/span&gt; =&amp;gt; false &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.

&lt;span class=&quot;hljs-keyword&quot;&gt;Lemma&lt;/span&gt; is_some_None {α} (x : option α)
  : x = None -&amp;gt; is_some x &amp;lt;&amp;gt; true.
&lt;span class=&quot;hljs-keyword&quot;&gt;Proof&lt;/span&gt;. &lt;span class=&quot;hljs-built_in&quot;&gt;intros&lt;/span&gt; H. &lt;span class=&quot;hljs-built_in&quot;&gt;rewrite&lt;/span&gt; H. &lt;span class=&quot;hljs-built_in&quot;&gt;discriminate&lt;/span&gt;. &lt;span class=&quot;hljs-keyword&quot;&gt;Qed&lt;/span&gt;.

&lt;span class=&quot;hljs-keyword&quot;&gt;Definition&lt;/span&gt; from_option {α}
    (x : option α) (some : is_some x = true)
  : α :=
  &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; x &lt;span class=&quot;hljs-built_in&quot;&gt;as&lt;/span&gt; y &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; x = y -&amp;gt; α &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Some&lt;/span&gt; x =&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; =&amp;gt; x
  | &lt;span class=&quot;hljs-type&quot;&gt;None&lt;/span&gt; =&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; equ =&amp;gt; False_rect α (is_some_None x equ some)
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt; eq_refl.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In &lt;code class=&quot;hljs language-coq&quot;&gt;from_option&lt;/code&gt;, we construct two proofs without using tactics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;False_rect α (is_some_None x equ some)&lt;/code&gt; to exclude the absurd case&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;eq_refl&lt;/code&gt; in conjunction with a dependent pattern matching (if you are
not familiar with this trick: the main idea is to allow Coq to
“remember” that &lt;code class=&quot;hljs language-coq&quot;&gt;x = None&lt;/code&gt; in the second branch)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can use another approach. We can decide to implement &lt;code class=&quot;hljs language-coq&quot;&gt;from_option&lt;/code&gt;
with a proof script.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Definition&lt;/span&gt; from_option&apos; {α}
    (x : option α) (some : is_some x = true)
  : α.
&lt;span class=&quot;hljs-keyword&quot;&gt;Proof&lt;/span&gt;.
  &lt;span class=&quot;hljs-built_in&quot;&gt;case_eq&lt;/span&gt; x.
  + &lt;span class=&quot;hljs-built_in&quot;&gt;intros&lt;/span&gt; y &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt;.
    &lt;span class=&quot;hljs-built_in&quot;&gt;exact&lt;/span&gt; y.
  + &lt;span class=&quot;hljs-built_in&quot;&gt;intros&lt;/span&gt; equ.
    &lt;span class=&quot;hljs-built_in&quot;&gt;rewrite&lt;/span&gt; equ &lt;span class=&quot;hljs-built_in&quot;&gt;in&lt;/span&gt; some.
    now &lt;span class=&quot;hljs-built_in&quot;&gt;apply&lt;/span&gt; is_some_None &lt;span class=&quot;hljs-built_in&quot;&gt;in&lt;/span&gt; some.
&lt;span class=&quot;hljs-keyword&quot;&gt;Defined&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is a third approach we can consider: mixing Gallina terms and tactics.
This is possible thanks to the &lt;code class=&quot;hljs language-coq&quot;&gt;ltac:()&lt;/code&gt; feature.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Definition&lt;/span&gt; from_option&apos;&apos; {α}
    (x : option α) (some : is_some x = true)
  : α :=
  &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; x &lt;span class=&quot;hljs-built_in&quot;&gt;as&lt;/span&gt; y &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; x = y -&amp;gt; α &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;Some&lt;/span&gt; x =&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; =&amp;gt; x
  | &lt;span class=&quot;hljs-type&quot;&gt;None&lt;/span&gt; =&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; equ =&amp;gt; ltac:(&lt;span class=&quot;hljs-built_in&quot;&gt;rewrite&lt;/span&gt; equ &lt;span class=&quot;hljs-built_in&quot;&gt;in&lt;/span&gt; some;
                             now &lt;span class=&quot;hljs-built_in&quot;&gt;apply&lt;/span&gt; is_some_None &lt;span class=&quot;hljs-built_in&quot;&gt;in&lt;/span&gt; some)
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt; eq_refl.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When Coq encounters &lt;code class=&quot;hljs language-coq&quot;&gt;ltac:()&lt;/code&gt;, it treats it as a hole. It sets up a
corresponding goal, and tries to solve it with the supplied tactic.&lt;/p&gt;
&lt;p&gt;Conversely, there exists ways to construct terms in Gallina when writing a proof
script. Certain tactics take such terms as arguments. Besides, Ltac provides
&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;constr&lt;/span&gt;:()&lt;/code&gt; and &lt;code class=&quot;hljs language-coq&quot;&gt;uconstr:()&lt;/code&gt; which work similarly to
&lt;code class=&quot;hljs language-coq&quot;&gt;ltac:()&lt;/code&gt;. The difference between &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;constr&lt;/span&gt;:()&lt;/code&gt; and
&lt;code class=&quot;hljs language-coq&quot;&gt;uconstr:()&lt;/code&gt; is that Coq will try to assign a type to the argument of
&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;constr&lt;/span&gt;:()&lt;/code&gt;, but will leave the argument of &lt;code class=&quot;hljs language-coq&quot;&gt;uconstr:()&lt;/code&gt; untyped.&lt;/p&gt;
&lt;p&gt;For instance, consider the following tactic definition.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Tactic&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;Notation&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;wrap_id&quot;&lt;/span&gt; uconstr(x) :=
  &lt;span class=&quot;hljs-keyword&quot;&gt;let&lt;/span&gt; f := uconstr:(&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; x =&amp;gt; x) &lt;span class=&quot;hljs-built_in&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;hljs-built_in&quot;&gt;exact&lt;/span&gt; (f x).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt; the argument of &lt;code class=&quot;hljs language-coq&quot;&gt;wrap_id&lt;/code&gt; and &lt;code class=&quot;hljs language-coq&quot;&gt;f&lt;/code&gt; the anonymous identity function
are not typed. It is only when they are composed together as an argument of
&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;exact&lt;/span&gt;&lt;/code&gt; (which expects a typed argument, more precisely of the type of the
goal) that Coq actually tries to type check it.&lt;/p&gt;
&lt;p&gt;As a consequence, &lt;code class=&quot;hljs language-coq&quot;&gt;wrap_id&lt;/code&gt; generates a specialized identity function for
each specific context.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Definition&lt;/span&gt; zero : nat := ltac:(wrap_id &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The generated anonymous identity function is &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; x : nat =&amp;gt; x&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Definition&lt;/span&gt; empty_list α : list α := ltac:(wrap_id nil).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The generated anonymous identity function is &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; x : list α =&amp;gt; x&lt;/code&gt;.
Besides, we do not need to give more type information about &lt;code class=&quot;hljs language-coq&quot;&gt;nil&lt;/code&gt;. If
&lt;code class=&quot;hljs language-coq&quot;&gt;wrap_id&lt;/code&gt; were to be expecting a typed term, we would have to replace
&lt;code class=&quot;hljs language-coq&quot;&gt;nil&lt;/code&gt; by [(@nil α)].&lt;/p&gt;
&lt;h2&gt;Beware the Automation Elephant in the Room&lt;/h2&gt;
&lt;p&gt;Proofs and computational programs are encoded in Coq as terms, but there is a
fundamental difference between them, and it is highlighted by one of the axioms
provided by the Coq standard library: proof irrelevance.&lt;/p&gt;
&lt;p&gt;Proof irrelevance states that two proofs of the same theorem (i.e., two proof
terms which share the same type) are essentially equivalent, and can be
substituted without threatening the trustworthiness of the system. From a
formal methods point of view, it makes sense. Even if we value “beautiful
proofs,” we mostly want correct proofs.&lt;/p&gt;
&lt;p&gt;The same reasoning does &lt;em&gt;not&lt;/em&gt; apply to computational programs. Two functions of
type &lt;code class=&quot;hljs language-coq&quot;&gt;nat -&amp;gt; nat -&amp;gt; nat&lt;/code&gt; are unlikely to be equivalent.  For instance,
&lt;code class=&quot;hljs language-coq&quot;&gt;add&lt;/code&gt;, &lt;code class=&quot;hljs language-coq&quot;&gt;mul&lt;/code&gt; or &lt;code class=&quot;hljs language-coq&quot;&gt;sub&lt;/code&gt; share the same type, but computes
totally different results.&lt;/p&gt;
&lt;p&gt;Using tactics such as &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;auto&lt;/span&gt;&lt;/code&gt; to generate terms which do not live inside
&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Prop&lt;/span&gt;&lt;/code&gt; is risky, to say the least. For instance,&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Definition&lt;/span&gt; add (x y : nat) : nat := ltac:(&lt;span class=&quot;hljs-built_in&quot;&gt;auto&lt;/span&gt;).
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This works, but it is certainly not what you would expect:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;add = &lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; y : nat =&amp;gt; y
     : nat -&amp;gt; nat -&amp;gt; nat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That being said, if we keep that in mind, and assert the correctness of the
generated programs (either by providing a proof, or by extensively testing it),
there is no particular reason not to use Ltac to generate terms when it makes
sense.&lt;/p&gt;
&lt;p&gt;Dependently typed programming can help you here. If we decorate the return type of
a function with the expected properties of the result wrt. the function’s
arguments, we can ensure the function is correct, and conversely prevent tactics
such as &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;auto&lt;/span&gt;&lt;/code&gt; to generate “incorrect” terms. Interested readers may
refer to &lt;a href=&quot;/~lthms/posts/StronglySpecifiedFunctions.html&quot; class=&quot;hover-lavender&quot; marked=&quot;&quot;&gt;the dedicated series on this very
website&lt;/a&gt;.&lt;/p&gt;
        
      </description>
    </item>
    
    
    
    <item>
      <title>Pattern Matching on Types and Contexts</title>
      <link>https://soap.coffee/~lthms/posts/LtacPatternMatching.html</link>
      <guid>https://soap.coffee/~lthms/posts/LtacPatternMatching.html</guid>
      <pubDate>August 28, 2020</pubDate>
      <description>
        
        &lt;h1&gt;Pattern Matching on Types and Contexts&lt;/h1&gt;&lt;div id=&quot;tags-list&quot;&gt;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#tag&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&amp;nbsp;&lt;a href=&quot;/~lthms/tags/coq.html&quot; class=&quot;tag hover-peach&quot; marked=&quot;&quot;&gt;coq&lt;/a&gt; &lt;/div&gt;
&lt;p&gt;In the &lt;a href=&quot;/~lthms/posts/LtacMetaprogramming.html&quot; class=&quot;hover-mint&quot; marked=&quot;&quot;&gt;a previous article&lt;/a&gt; of our series on
Ltac, we have shown how tactics allow for constructing Coq terms incrementally.
Ltac programs (“proof scripts”) generate terms, and the shape of said terms can
be very different regarding the initial context. For instance, &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;induction&lt;/span&gt; x&lt;/code&gt; will refine the current goal by using an inductive principle dedicated to
the type of &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is possible because Ltac allows for pattern matching on types and
contexts. In this article, we give a short introduction on this feature of
key importance.&lt;/p&gt;
&lt;h2&gt;To &lt;code class=&quot;hljs language-coq&quot;&gt;lazymatch&lt;/code&gt; or to &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Gallina provides one pattern matching construction, whose semantics is always
the same: for a given term, the first pattern to match will always be selected.
On the contrary, Ltac provides several pattern matching constructions with
different semantics. This key difference has probably been motivated because
Ltac is not a total language: a tactic may not always succeed.&lt;/p&gt;
&lt;p&gt;Ltac programmers can use &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt;&lt;/code&gt; or &lt;code class=&quot;hljs language-coq&quot;&gt;lazymatch&lt;/code&gt;. One the one hand,
with &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt;&lt;/code&gt;, if one pattern matches, but the branch body fails, Coq will
backtrack and try the next branch. On the other hand, &lt;code class=&quot;hljs language-coq&quot;&gt;lazymatch&lt;/code&gt; will
stop with an error.&lt;/p&gt;
&lt;p&gt;So, for instance, the two following tactics will print two different messages:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Ltac&lt;/span&gt; match_failure :=
  &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; goal &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt;
    =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fail in first branch&quot;&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt;
    =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fail in second branch&quot;&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.

&lt;span class=&quot;hljs-keyword&quot;&gt;Ltac&lt;/span&gt; lazymatch_failure :=
  lazymatch goal &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt;
    =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fail in first branch&quot;&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt;
    =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fail in second branch&quot;&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can try that quite easily by starting a dumb goal (eg. &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Goal&lt;/span&gt; (True).&lt;/code&gt;)
and call our tactic. For &lt;code class=&quot;hljs language-coq&quot;&gt;match_failure&lt;/code&gt;, we get:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;Ltac call to &quot;match_failure&quot; failed.
Error: Tactic failure: fail in second branch.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the other hand, for &lt;code class=&quot;hljs language-coq&quot;&gt;lazymatch_failure&lt;/code&gt;, we get:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs&quot;&gt;Ltac call to &quot;match_failure&apos;&quot; failed.
Error: Tactic failure: fail in first branch.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moreover, pattern matching allows for matching over &lt;em&gt;patterns&lt;/em&gt;, not just
constants. Here, Ltac syntax differs from Gallina’s. In Gallina, if a
variable name is used in a pattern, Gallina creates a new variable in the
scope of the related branch. If a variable with the same name already
existed, it is shadowed. On the contrary, in Ltac, using a variable name
as-is in a pattern implies an equality check.&lt;/p&gt;
&lt;p&gt;To illustrate this difference, we can take the example of the following
tactic.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Ltac&lt;/span&gt; successive x y :=
  lazymatch y &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; x =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;idtac&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt; =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;fail&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;successive x y&lt;/code&gt; will fail if &lt;code class=&quot;hljs language-coq&quot;&gt;y&lt;/code&gt; is not the successor of
&lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt;. On the contrary, the “syntactically equivalent” function in Gallina
will exhibit a totally different behavior.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Definition&lt;/span&gt; successor (x y : nat) : bool :=
  &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; y &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; x =&amp;gt; true
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt; =&amp;gt; false
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, the first branch of the pattern match is systematically selected when
&lt;code class=&quot;hljs language-coq&quot;&gt;y&lt;/code&gt; is not &lt;code class=&quot;hljs language-coq&quot;&gt;O&lt;/code&gt;, and in this branch, the argument &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt; is shadowed by the
predecessor of &lt;code class=&quot;hljs language-coq&quot;&gt;y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For Ltac to adopt a behavior similar to Gallina, the &lt;code class=&quot;hljs language-coq&quot;&gt;?&lt;/code&gt; prefix shall be
used. For instance, the following tactic will check whether its argument
has a known successor, prints it if it does, or fail otherwise.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Ltac&lt;/span&gt; print_pred_or_zero x :=
  &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; x &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; ?x =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;idtac&lt;/span&gt; x
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt; =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;fail&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the one hand, &lt;code class=&quot;hljs language-coq&quot;&gt;print_pred_or_zero &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;&lt;/code&gt; will print &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;&lt;/code&gt;. On the
other hand, if there exists a variable &lt;code class=&quot;hljs language-coq&quot;&gt;x : nat&lt;/code&gt; in the context, calling
&lt;code class=&quot;hljs language-coq&quot;&gt;print_pred_or_zero x&lt;/code&gt; will fail, since the exact value of &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt; is
not known.&lt;/p&gt;
&lt;h3&gt;Pattern Matching on Types with &lt;code class=&quot;hljs language-coq&quot;&gt;type of&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code class=&quot;hljs language-coq&quot;&gt;type of&lt;/code&gt; operator can be used in conjunction to pattern matching to
generate different terms according to the type of a variable. We could
leverage this to reimplement &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;induction&lt;/span&gt;&lt;/code&gt; for instance.&lt;/p&gt;
&lt;p&gt;As an example, we propose the following &lt;code class=&quot;hljs language-coq&quot;&gt;not_nat&lt;/code&gt; tactic which, given an
argument &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt;, fails if &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt; is of type &lt;code class=&quot;hljs language-coq&quot;&gt;nat&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Ltac&lt;/span&gt; not_nat x :=
  lazymatch type of x &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;nat&lt;/span&gt; =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;argument is of type nat&quot;&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt; =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;idtac&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With this definition, &lt;code class=&quot;hljs language-coq&quot;&gt;not_nat true&lt;/code&gt; succeeds since &lt;code class=&quot;hljs language-coq&quot;&gt;true&lt;/code&gt; is of
type &lt;code class=&quot;hljs language-coq&quot;&gt;bool&lt;/code&gt;, and &lt;code class=&quot;hljs language-coq&quot;&gt;not_nat O&lt;/code&gt; since &lt;code class=&quot;hljs language-coq&quot;&gt;O&lt;/code&gt; encodes &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; in
&lt;code class=&quot;hljs language-coq&quot;&gt;nat&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We can also use the &lt;code class=&quot;hljs language-coq&quot;&gt;?&lt;/code&gt; prefix to write true pattern. For instance, the
following tactic will fail if the type of its supplied argument has at least
one parameter.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Ltac&lt;/span&gt; not_param_type x :=
  lazymatch type of x &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;?f&lt;/span&gt; ?a =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;fail&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;argument is of type with parameter&quot;&lt;/span&gt;
  | &lt;span class=&quot;hljs-type&quot;&gt;_&lt;/span&gt; =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;idtac&lt;/span&gt;
  &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Both &lt;code class=&quot;hljs language-coq&quot;&gt;not_param_type (@nil nat)&lt;/code&gt; of type &lt;code class=&quot;hljs language-coq&quot;&gt;list nat&lt;/code&gt; and &lt;code class=&quot;hljs language-coq&quot;&gt;@eq_refl nat &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt; of type &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt; fail, but &lt;code class=&quot;hljs language-coq&quot;&gt;not_param_type &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt; of type
&lt;code class=&quot;hljs language-coq&quot;&gt;nat&lt;/code&gt; succeeds. *)&lt;/p&gt;
&lt;h2&gt;Pattern Matching on the Context with &lt;code class=&quot;hljs language-coq&quot;&gt;goal&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Lastly, we discuss how Ltac allows for inspecting the context (&lt;em&gt;i.e.&lt;/em&gt;, the
hypotheses and the goal) using the &lt;code class=&quot;hljs language-coq&quot;&gt;goal&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;For instance, we propose a naive implementation of the &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;subst&lt;/span&gt;&lt;/code&gt; tactic
as follows.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Ltac&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;subst&lt;/span&gt;&apos; :=
  &lt;span class=&quot;hljs-built_in&quot;&gt;repeat&lt;/span&gt;
    &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; goal &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
    | &lt;span class=&quot;hljs-type&quot;&gt;H&lt;/span&gt; :  ?x = &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; |&lt;span class=&quot;hljs-type&quot;&gt;- context&lt;/span&gt;[?x]
      =&amp;gt; &lt;span class=&quot;hljs-built_in&quot;&gt;repeat&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;rewrite&lt;/span&gt; H; &lt;span class=&quot;hljs-built_in&quot;&gt;clear&lt;/span&gt; H
    &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With &lt;code class=&quot;hljs language-coq&quot;&gt;goal&lt;/code&gt;, patterns are of the form &lt;code class=&quot;hljs language-coq&quot;&gt;H : (&lt;span class=&quot;hljs-built_in&quot;&gt;pattern&lt;/span&gt;), ... |&lt;span class=&quot;hljs-type&quot;&gt;- (pattern&lt;/span&gt;)&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;At the left side of &lt;code class=&quot;hljs language-coq&quot;&gt;|&lt;span class=&quot;hljs-type&quot;&gt;-&lt;/span&gt;&lt;/code&gt;, we match on hypotheses. Beware that
contrary to variable names in pattern, hypothesis names behaves as in
Gallina (i.e., fresh binding, shadowing, etc.). In the branch, we are
looking for equations, i.e., a hypothesis of the form &lt;code class=&quot;hljs language-coq&quot;&gt;?x = &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;At the right side of &lt;code class=&quot;hljs language-coq&quot;&gt;|&lt;span class=&quot;hljs-type&quot;&gt;-&lt;/span&gt;&lt;/code&gt;, we match on the goal.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In both cases, Ltac makes available an interesting operator,
&lt;code class=&quot;hljs language-coq&quot;&gt;context[(&lt;span class=&quot;hljs-built_in&quot;&gt;pattern&lt;/span&gt;)&lt;/code&gt;], which is satisfied if &lt;code class=&quot;hljs language-coq&quot;&gt;(&lt;span class=&quot;hljs-built_in&quot;&gt;pattern&lt;/span&gt;)&lt;/code&gt; appears somewhere in
the object we are pattern matching against. So, the branch of the &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt;&lt;/code&gt;
reads as follows: we are looking for an equation &lt;code class=&quot;hljs language-coq&quot;&gt;H&lt;/code&gt; which specifies the
value of an object &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt; which appears in the goal. If such an equation
exists, &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;subst&lt;/span&gt;&apos;&lt;/code&gt; tries to &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;rewrite&lt;/span&gt; x&lt;/code&gt; as many times as possible.&lt;/p&gt;
&lt;p&gt;This implementation of &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;subst&lt;/span&gt;&apos;&lt;/code&gt; is very fragile, and will not work if the
equation is of the form &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; = ?x&lt;/code&gt;, and it may behave poorly if we have
“transitive equations”, such as there exists hypotheses &lt;code class=&quot;hljs language-coq&quot;&gt;?x = ?y&lt;/code&gt; and &lt;code class=&quot;hljs language-coq&quot;&gt;?y = &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt;&lt;/code&gt;. Motivated readers may be interested in proposing a more robust
implementation of &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;subst&lt;/span&gt;&apos;&lt;/code&gt;.&lt;/p&gt;
        
      </description>
    </item>
    
    
    
    <item>
      <title>Ltac is an Imperative Metaprogramming Language</title>
      <link>https://soap.coffee/~lthms/posts/LtacMetaprogramming.html</link>
      <guid>https://soap.coffee/~lthms/posts/LtacMetaprogramming.html</guid>
      <pubDate>August 28, 2020</pubDate>
      <description>
        
        &lt;h1&gt;Ltac is an Imperative Metaprogramming Language&lt;/h1&gt;&lt;div id=&quot;tags-list&quot;&gt;&lt;span class=&quot;icon&quot;&gt;&lt;svg&gt;&lt;use href=&quot;/~lthms/img/icons.svg#tag&quot;&gt;&lt;/use&gt;&lt;/svg&gt;&lt;/span&gt;&amp;nbsp;&lt;a href=&quot;/~lthms/tags/coq.html&quot; class=&quot;tag hover-sky&quot; marked=&quot;&quot;&gt;coq&lt;/a&gt; &lt;/div&gt;
&lt;p&gt;Coq is often depicted as an &lt;em&gt;interactive&lt;/em&gt; proof assistant, thanks to its
proof environment. Inside the proof environment, Coq presents the user a
goal, and said user solves said goal by means of tactics which describes a
logical reasoning. For instance, to reason by induction, one can use the
&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;induction&lt;/span&gt;&lt;/code&gt; tactic, while a simple case analysis can rely on the
&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;destruct&lt;/span&gt;&lt;/code&gt; or &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;case_eq&lt;/span&gt;&lt;/code&gt; tactics, etc.  It is not uncommon for new
Coq users to be introduced to Ltac, the Coq default tactic language, using this
proof-centric approach. This is not surprising, since writing proofs remains
the main use case for Ltac. In practice, though, this discourse remains an
abstraction which hides away what actually happens under the hood when Coq
executes a proof script.&lt;/p&gt;
&lt;p&gt;To really understand what Ltac is about, we need to recall ourselves that
Coq kernel is mostly a type checker. A theorem statement is expressed as a
“type” (which lives in a dedicated sort called &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Prop&lt;/span&gt;&lt;/code&gt;), and a proof of
this theorem is a term of this type, just like the term &lt;code class=&quot;hljs language-coq&quot;&gt;S (S O)&lt;/code&gt; (&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;2&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;2&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)
is of type &lt;code class=&quot;hljs language-coq&quot;&gt;nat&lt;/code&gt;.  Proving a theorem in Coq requires to construct a term
of the type encoding said theorem, and Ltac allows for incrementally
constructing this term, one step at a time.&lt;/p&gt;
&lt;p&gt;Ltac generates terms, therefore it is a metaprogramming language. It does it
incrementally, by using primitives to modifying an implicit state, therefore
it is an imperative language. Henceforth, it is an imperative
metaprogramming language.&lt;/p&gt;
&lt;p&gt;To summarize, a goal presented by Coq inside the environment proof is a hole
within the term being constructed. It is presented to users as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A list of “hypotheses,” which are nothing more than the variables
in the scope of the hole&lt;/li&gt;
&lt;li&gt;A type, which is the type of the term to construct to fill the hole&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We illustrate what happens under the hood of Coq executes a simple proof
script. One can use the &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;Proof&lt;/span&gt;&lt;/code&gt; vernacular command to exhibit
this.&lt;/p&gt;
&lt;p&gt;We illustrate how Ltac works with the following example.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Theorem&lt;/span&gt; add_n_O : &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; (n : nat), n + O = n.
&lt;span class=&quot;hljs-keyword&quot;&gt;Proof&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Proof&lt;/span&gt;&lt;/code&gt; vernacular command starts the proof environment. Since no
tactic has been used, the term we are trying to construct consists solely in a
hole, while Coq presents us a goal with no hypothesis, and with the exact type
of our theorem, that is &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; (n : nat), n + O = n&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A typical Coq course will explain to students the &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;intro&lt;/span&gt;&lt;/code&gt; tactic allows for
turning the premise of an implication into an hypothesis within the context.&lt;/p&gt;
&lt;p class=&quot;katex-block&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi&gt;Q&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C \vdash P \rightarrow Q
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Q&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;becomes&lt;/p&gt;
&lt;p class=&quot;katex-block&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;C&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mtext&gt;&amp;nbsp;&lt;/mtext&gt;&lt;mi&gt;P&lt;/mi&gt;&lt;mo&gt;⊢&lt;/mo&gt;&lt;mi&gt;Q&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;C,\ P \vdash Q
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.07153em;&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.13889em;&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;⊢&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8778em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;Q&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is a fundamental rule of deductive reasoning, and &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;intro&lt;/span&gt;&lt;/code&gt; encodes it.
It achieves this by refining the current hole into an anonymous function.
When we use&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  &lt;span class=&quot;hljs-built_in&quot;&gt;intro&lt;/span&gt; n.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;it refines the term&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  ?Goal1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;into&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  &lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; (n : nat) =&amp;gt; ?Goal2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next step of this proof is to reason about induction on &lt;code class=&quot;hljs&quot;&gt;n&lt;/code&gt;. For &lt;code class=&quot;hljs&quot;&gt;nat&lt;/code&gt;,
it means that to be able to prove&lt;/p&gt;
&lt;p class=&quot;katex-block&quot;&gt;&lt;span class=&quot;katex-display&quot;&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot; display=&quot;block&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∀&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;P&lt;/mi&gt;&lt;mtext&gt;&amp;nbsp;&lt;/mtext&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\forall n, \mathrm{P}\ n
&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;∀&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathrm&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mspace&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;we need to prove that&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;P&lt;/mi&gt;&lt;mtext&gt;&amp;nbsp;&lt;/mtext&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{P}\ 0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathrm&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mspace&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;∀&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;P&lt;/mi&gt;&lt;mtext&gt;&amp;nbsp;&lt;/mtext&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo&gt;→&lt;/mo&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;P&lt;/mi&gt;&lt;mtext&gt;&amp;nbsp;&lt;/mtext&gt;&lt;mo stretchy=&quot;false&quot;&gt;(&lt;/mo&gt;&lt;mi&gt;S&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mo stretchy=&quot;false&quot;&gt;)&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\forall n, \mathrm{P}\ n \rightarrow \mathrm{P}\ (S n)&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.8889em;vertical-align:-0.1944em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;∀&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.1667em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathrm&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mspace&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;→&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathrm&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mspace&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.05764em;&quot;&gt;S&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;induction&lt;/span&gt;&lt;/code&gt; tactic effectively turns our goal into two subgoals. But
why is that? Because, under the hood, Ltac is refining the current goal using
the &lt;code class=&quot;hljs language-coq&quot;&gt;nat_ind&lt;/code&gt; function automatically generated by Coq when &lt;code class=&quot;hljs language-coq&quot;&gt;nat&lt;/code&gt;
was defined. The type of &lt;code class=&quot;hljs language-coq&quot;&gt;nat_ind&lt;/code&gt; is&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; (P : nat -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;Prop&lt;/span&gt;),
    P &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;
    -&amp;gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; n : nat, P n -&amp;gt; P (S n))
    -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; n : nat, P n
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Interestingly enough, &lt;code class=&quot;hljs language-coq&quot;&gt;nat_ind&lt;/code&gt; is not an axiom. It is a regular Coq
function, whose definition is&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  &lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; (P : nat -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;Prop&lt;/span&gt;) (f : P &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)
      (f0 : &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; n : nat, P n -&amp;gt; P (S n)) =&amp;gt;
  &lt;span class=&quot;hljs-built_in&quot;&gt;fix&lt;/span&gt; F (n : nat) : P n :=
    &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; n &lt;span class=&quot;hljs-built_in&quot;&gt;as&lt;/span&gt; n0 &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; (P n0) &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
    | &lt;span class=&quot;hljs-type&quot;&gt;0&lt;/span&gt; =&amp;gt; f
    | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; n0 =&amp;gt; f0 n0 (F n0)
    &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, after executing&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  &lt;span class=&quot;hljs-built_in&quot;&gt;induction&lt;/span&gt; n.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The hidden term we are constructing becomes&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n : nat =&amp;gt;
     nat_ind
       (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n0 : nat =&amp;gt; n0 + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = n0)
       ?Goal3
       (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; (n0 : nat) (IHn : n0 + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = n0) =&amp;gt; ?Goal4)
       n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And Coq presents us two goals.&lt;/p&gt;
&lt;p&gt;First, we need to prove &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;P&lt;/mi&gt;&lt;mtext&gt;&amp;nbsp;&lt;/mtext&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;\mathrm{P}\ 0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathrm&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;mspace&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;, &lt;em&gt;i.e.&lt;/em&gt;,
&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;mn&gt;0&lt;/mn&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;0 + 0 = 0&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.7278em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mbin&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2222em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.2778em;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6444em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;. Similarly to Coq presenting a goal when what we are actually doing
is constructing a term, the use of &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;=&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;=&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.3669em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mrel&quot;&gt;=&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; and &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo&gt;+&lt;/mo&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;+&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:0.6667em;vertical-align:-0.0833em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;+&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (&lt;em&gt;i.e.&lt;/em&gt;, the Coq notations
mechanism) hides much here. We can ask Coq to be more explicit by using the
vernacular command &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;Printing&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;All&lt;/span&gt;&lt;/code&gt; to learn that when Coq presents us
a goal of the form &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;, it is actually looking for a term of type
&lt;code class=&quot;hljs language-coq&quot;&gt;@eq nat (Nat.add O O) O&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;Nat.add&lt;/code&gt; is a regular Coq (recursive) function.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  &lt;span class=&quot;hljs-built_in&quot;&gt;fix&lt;/span&gt; add (n m : nat) {struct n} : nat :=
    &lt;span class=&quot;hljs-keyword&quot;&gt;match&lt;/span&gt; n &lt;span class=&quot;hljs-built_in&quot;&gt;with&lt;/span&gt;
    | &lt;span class=&quot;hljs-type&quot;&gt;0&lt;/span&gt; =&amp;gt; m
    | &lt;span class=&quot;hljs-type&quot;&gt;S&lt;/span&gt; p =&amp;gt; S (add p m)
    &lt;span class=&quot;hljs-keyword&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly, &lt;code class=&quot;hljs language-coq&quot;&gt;eq&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; an axiom. It is a regular inductive type, defined
as follows.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Inductive&lt;/span&gt; eq (A : &lt;span class=&quot;hljs-keyword&quot;&gt;Type&lt;/span&gt;) (x : A) : A -&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;Prop&lt;/span&gt; :=
| &lt;span class=&quot;hljs-type&quot;&gt;eq_refl&lt;/span&gt; : eq A x x
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Coming back to our current goal, proving &lt;code class=&quot;hljs language-coq&quot;&gt;@eq nat (Nat.add &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;&lt;label for=&quot;fn1&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn1&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-right sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;That is, &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt; &lt;/span&gt;
&lt;/span&gt;
requires to construct a term of a type whose only constructor is
&lt;code class=&quot;hljs language-coq&quot;&gt;eq_refl&lt;/code&gt;. &lt;code class=&quot;hljs language-coq&quot;&gt;eq_refl&lt;/code&gt; accepts one argument, and encodes the proof
that said argument is equal to itself. In practice, Coq type checker will accept
the term &lt;code class=&quot;hljs language-coq&quot;&gt;@eq_refl &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; x&lt;/code&gt; when it expects a term of type &lt;code class=&quot;hljs language-coq&quot;&gt;@eq &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; x y&lt;/code&gt;
&lt;em&gt;if&lt;/em&gt; it can reduce &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt; and &lt;code class=&quot;hljs language-coq&quot;&gt;y&lt;/code&gt; to the same term.&lt;/p&gt;
&lt;p&gt;Is it the case for &lt;code class=&quot;hljs language-coq&quot;&gt;@eq nat (Nat.add &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;) &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt;? It is, since by definition
of &lt;code class=&quot;hljs language-coq&quot;&gt;Nat.add&lt;/code&gt;, &lt;code class=&quot;hljs language-coq&quot;&gt;Nat.add &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; x&lt;/code&gt; is reduced to &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt;. We can use the
&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;reflexivity&lt;/span&gt;&lt;/code&gt; tactic to tell Coq to fill the current hole with
&lt;code class=&quot;hljs language-coq&quot;&gt;eq_refl&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  + &lt;span class=&quot;hljs-built_in&quot;&gt;reflexivity&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Suspicious readers may rely on &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;Proof&lt;/span&gt;&lt;/code&gt; to verify this assertion.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n : nat =&amp;gt;
     nat_ind
       (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n0 : nat =&amp;gt; n0 + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = n0)
       eq_refl
       (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; (n0 : nat) (IHn : n0 + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = n0) =&amp;gt; ?Goal4)
       n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;?Goal3&lt;/code&gt; has indeed be replaced by &lt;code class=&quot;hljs&quot;&gt;eq_refl&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;One goal remains, as we need to prove that if &lt;code class=&quot;hljs language-coq&quot;&gt;n + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = n&lt;/code&gt;, then &lt;code class=&quot;hljs language-coq&quot;&gt;S n + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = S n&lt;/code&gt;. Coq can reduce &lt;code class=&quot;hljs language-coq&quot;&gt;S n + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt; to &lt;code class=&quot;hljs language-coq&quot;&gt;S (n + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)&lt;/code&gt; by definition
of &lt;code class=&quot;hljs language-coq&quot;&gt;Nat.add&lt;/code&gt;, but it cannot reduce &lt;code class=&quot;hljs language-coq&quot;&gt;S n&lt;/code&gt; more than it already is.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  + &lt;span class=&quot;hljs-built_in&quot;&gt;cbn&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We cannot just use &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;reflexivity&lt;/span&gt;&lt;/code&gt; here (&lt;em&gt;i.e.&lt;/em&gt;, fill the hole with
&lt;code class=&quot;hljs language-coq&quot;&gt;eq_refl&lt;/code&gt;), since &lt;code class=&quot;hljs language-coq&quot;&gt;S (n + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;)&lt;/code&gt; and &lt;code class=&quot;hljs language-coq&quot;&gt;S n&lt;/code&gt; cannot be reduced to
the same term.&lt;/p&gt;
&lt;p&gt;However, at this point of the proof, we have the &lt;code class=&quot;hljs language-coq&quot;&gt;IHn&lt;/code&gt; hypothesis (&lt;em&gt;i.e.&lt;/em&gt;, the
&lt;code class=&quot;hljs language-coq&quot;&gt;IHn&lt;/code&gt; argument of the anonymous function whose body we are trying to
construct). The &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;rewrite&lt;/span&gt;&lt;/code&gt; tactic allows for substituting in a type an
occurrence of &lt;code class=&quot;hljs language-coq&quot;&gt;x&lt;/code&gt; by &lt;code class=&quot;hljs language-coq&quot;&gt;y&lt;/code&gt; as long as we have a proof of &lt;code class=&quot;hljs language-coq&quot;&gt;x = y&lt;/code&gt;. *)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;    &lt;span class=&quot;hljs-built_in&quot;&gt;rewrite&lt;/span&gt; IHn.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Similarly to &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;induction&lt;/span&gt;&lt;/code&gt; using a dedicated function, &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;rewrite&lt;/span&gt;&lt;/code&gt; refines
the current hole with the &lt;code class=&quot;hljs language-coq&quot;&gt;eq_ind_r&lt;/code&gt; function&lt;label for=&quot;fn2&quot; class=&quot;sidenote-number margin-toggle&quot;&gt;&lt;/label&gt;&lt;input id=&quot;fn2&quot; type=&quot;checkbox&quot; class=&quot;margin-toggle&quot;&gt;&lt;span class=&quot;note-left sidenote note&quot;&gt;&lt;span class=&quot;footnote-p&quot;&gt;Again, not an axiom. &lt;/span&gt;
&lt;/span&gt;. Replacing &lt;code class=&quot;hljs language-coq&quot;&gt;n + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt;&lt;/code&gt; with &lt;code class=&quot;hljs language-coq&quot;&gt;n&lt;/code&gt; transforms the goal into &lt;code class=&quot;hljs language-coq&quot;&gt;S n = S n&lt;/code&gt;. Here, we
can use &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;reflexivity&lt;/span&gt;&lt;/code&gt; (i.e., &lt;code class=&quot;hljs language-coq&quot;&gt;eq_refl&lt;/code&gt;) to conclude. *)&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;    &lt;span class=&quot;hljs-built_in&quot;&gt;reflexivity&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After this last tactic, the work is done. There is no more goal to fill inside
the proof term that we have carefully constructed.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;  (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n : nat =&amp;gt;
     nat_ind
       (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n0 : nat =&amp;gt; n0 + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = n0)
       eq_refl
       (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; (n0 : nat) (IHn : n0 + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = n0) =&amp;gt;
          eq_ind_r (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n1 : nat =&amp;gt; S n1 = S n0) eq_refl IHn)
       n)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can finally use &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Qed&lt;/span&gt;&lt;/code&gt; or &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Defined&lt;/span&gt;&lt;/code&gt; to tell Coq to type check this
term. That is, Coq does not trust Ltac, but rather type check the term to
verify it is correct. This way, in case Ltac has a bug which makes it
construct an ill-formed type, at the very least Coq can reject it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Qed&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In conclusion, tactics are used to incrementally refine hole inside a term
until the latter is complete. They do it in a very specific manner, to
encode certain reasoning rules.&lt;/p&gt;
&lt;p&gt;On the other hand, the &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;refine&lt;/span&gt;&lt;/code&gt; tactic provides a generic, low-level way
to do the same thing. Knowing how a given tactic works allows for mimicking
its behavior using the &lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;refine&lt;/span&gt;&lt;/code&gt; tactic.&lt;/p&gt;
&lt;p&gt;If we take the previous theorem as an example, we can prove it using this
alternative proof script.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;hljs language-coq&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;Theorem&lt;/span&gt; add_n_O&apos; : &lt;span class=&quot;hljs-keyword&quot;&gt;forall&lt;/span&gt; (n : nat), n + O = n.
&lt;span class=&quot;hljs-keyword&quot;&gt;Proof&lt;/span&gt;.
  &lt;span class=&quot;hljs-built_in&quot;&gt;refine&lt;/span&gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n =&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt;).
  &lt;span class=&quot;hljs-built_in&quot;&gt;refine&lt;/span&gt; (nat_ind (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n =&amp;gt; n + &lt;span class=&quot;hljs-number&quot;&gt;0&lt;/span&gt; = n) &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; n).
  + &lt;span class=&quot;hljs-built_in&quot;&gt;refine&lt;/span&gt; eq_refl.
  + &lt;span class=&quot;hljs-built_in&quot;&gt;refine&lt;/span&gt; (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; m IHm =&amp;gt; &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt;).
    &lt;span class=&quot;hljs-built_in&quot;&gt;refine&lt;/span&gt; (eq_ind_r (&lt;span class=&quot;hljs-keyword&quot;&gt;fun&lt;/span&gt; n =&amp;gt; S n = S m) &lt;span class=&quot;hljs-keyword&quot;&gt;_&lt;/span&gt; IHm).
    &lt;span class=&quot;hljs-built_in&quot;&gt;refine&lt;/span&gt; eq_refl.
&lt;span class=&quot;hljs-keyword&quot;&gt;Qed&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;
        
      </description>
    </item>
    
    
  </channel>
</rss>
