<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Ascetic Slug</title>
    <subtitle>Programming blog</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blog.janmasrovira.org/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.janmasrovira.org"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2021-06-02T00:00:00+00:00</updated>
    <id>https://blog.janmasrovira.org/atom.xml</id>
    <entry xml:lang="en">
        <title>Using dependent types to write proofs in Haskell</title>
        <published>2021-06-02T00:00:00+00:00</published>
        <updated>2021-06-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.janmasrovira.org/blog/dependent-haskell-proofs/"/>
        <id>https://blog.janmasrovira.org/blog/dependent-haskell-proofs/</id>
        
        <content type="html" xml:base="https://blog.janmasrovira.org/blog/dependent-haskell-proofs/">&lt;p&gt;&lt;strong&gt;Target audience&lt;&#x2F;strong&gt;: This blog is meant for intermediate&#x2F;advanced Haskell
readers, specially those interested in logic. If you are new to Haskell, this
blog will probably not be easy to follow.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;overview&quot;&gt;Overview&lt;&#x2F;h1&gt;
&lt;p&gt;We all know that we can use Haskell to write functional programs that compute
stuff. But can we also use Haskell to write mathematical proofs? Yes!&lt;&#x2F;p&gt;
&lt;p&gt;In case you have never been exposed to dependent types, the concept of writing
proofs with a programming language will surely sound alien to you. In this
blog I hope to give you an informal introduction to dependent types in Haskell
that will allow you to understand what does it mean to prove something in
Haskell and how to do it. I strongly recommend that you follow along with ghci
on your side.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Clarification&lt;&#x2F;strong&gt;. At the time of writing this, GHC does &lt;em&gt;not&lt;&#x2F;em&gt; have full
dependent types, however, as we will see, it has some features that allow us to
get pretty close to them. If you are looking for a language with full dependent
types I suggest that you look into &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agda&#x2F;agda&quot;&gt;Agda&lt;&#x2F;a&gt; or
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lean-lang.org&#x2F;&quot;&gt;Lean&lt;&#x2F;a&gt;. In this &lt;a href=&quot;..&#x2F;hilbert-edsl&quot;&gt;other blog&lt;&#x2F;a&gt; I present an
Agda implementation of a type safe domain specific language to write Hilbert
style proofs. Also, GHC should &lt;em&gt;not&lt;&#x2F;em&gt; be used as a serious proof assistant,
because, as we will see in this blog, it is very easy to prove false statements
in it.&lt;&#x2F;p&gt;
&lt;p&gt;You can find all related code to what I will present in this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;janmasrovira&#x2F;dependent-haskell&quot;&gt;gitlab
repository&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;extensions&quot;&gt;Extensions&lt;&#x2F;h1&gt;
&lt;p&gt;In order to get close to dependent types we need the help of some GHC extensions.
If you want to follow along, make sure to have the following extensions
enabled in ghci. I will comment on some of them when they become relevant to
the code I&#x27;m showing. Note that each extension links to the corresponding GHC
manual page.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;gadt.html&quot;&gt;&lt;code&gt;GADTs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Allow use of Generalised Algebraic Data Types (GADTs).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;scoped_type_variables.html#extension-ScopedTypeVariables&quot;&gt;&lt;code&gt;ScopedTypeVariables&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Enable lexical scoping of type variables explicitly
introduced with &lt;code&gt;forall&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;data_kinds.html&quot;&gt;&lt;code&gt;DataKinds&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Allow promotion of data types to kind level.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;poly_kinds.html#extension-PolyKinds&quot;&gt;&lt;code&gt;PolyKinds&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Allow kind polymorphic types.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;type_families.html&quot;&gt;&lt;code&gt;TypeFamilies&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Allow use and definition of indexed type and data families.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;type_operators.html#extension-TypeOperators&quot;&gt;&lt;code&gt;TypeOperators&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Allow the use and definition of types with operator names.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;instances.html#extension-UndecidableInstances&quot;&gt;&lt;code&gt;UndecidableInstances&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Permit definition of instances which may lead to
type-checker non-termination.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;equality-on-types&quot;&gt;Equality on types&lt;&#x2F;h1&gt;
&lt;p&gt;All proofs which I will present in this blog are proofs of equality. In fact,
we will only show theorems which can be expressed in a formula of the form&lt;&#x2F;p&gt;
&lt;p&gt;\[
∀x₁…∀xₙ(t₁ ⇒ … ⇒ tₘ ⇒ r = s),
\]&lt;&#x2F;p&gt;
&lt;p&gt;where $xᵢ$ are type variables and
$t₁,…,tₘ,r,s$ are types. So a first obvious step should be to define a type in
Haskell which expresses type equality (according to the rules of GHC). We
should agree that a the following header is a good place to start.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;data Equal a b where
   ...
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we should provide a constructor for this datatype. Of course, the
constructor should be a witness that &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt; are equal.
So we can define the desired constructor like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;data Equal a b where
  Witness :: (a ~ b) =&amp;gt; Equal a b
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Recall that the constraint &lt;code&gt;a ~ b&lt;&#x2F;code&gt; means precisely what we want. Namely, that
&lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt; are equal types according to GHC.&lt;&#x2F;p&gt;
&lt;p&gt;However, we are going to use an alternative definition, which is slightly
simpler and is already defined in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hackage.haskell.org&#x2F;package&#x2F;base-4.15.0.0&#x2F;docs&#x2F;Data-Type-Equality.html&quot;&gt;&lt;code&gt;base:Data.Type.Equality&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;data a :~: b where
  Refl :: a :~: a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Don&#x27;t get confused by the infix notation of &lt;code&gt;:~:&lt;&#x2F;code&gt;. It serves the same purpose
as &lt;code&gt;Equal&lt;&#x2F;code&gt;, but with infix notation (see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;type_operators.html#extension-TypeOperators&quot;&gt;&lt;code&gt;TypeOperators&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;). The constructor is
named &lt;code&gt;Refl&lt;&#x2F;code&gt; for &lt;em&gt;Reflexivity&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We are ready to write our first proof. Let us show that the equality relation
defined above is symmetric. Recall that in mathematics we say that a relation
$R$ is symmetric iff $∀x∀y(xRy⇒yRx)$.&lt;&#x2F;p&gt;
&lt;p&gt;Our next job is to find a type which faithfully represents the symmetry
proposition. Let&#x27;s use the following type.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;sym :: (x :~: y) -&amp;gt; (y :~: x)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First we need to convince ourselves that the type &lt;code&gt;(x :~: y) -&amp;gt; (y :~: x)&lt;&#x2F;code&gt;
faithfully represents a proposition stating the property of symmetry. In fact
if we use explicit quantification for &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt; and we interpret the
function type (&lt;code&gt;-&amp;gt;&lt;&#x2F;code&gt;) as an implication, it looks exactly like the mathematical
statement:&lt;&#x2F;p&gt;
&lt;p&gt;\[ ∀x∀y(xRy⇒yRx)
\]&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;forall x y. (x :~: y) -&amp;gt; (y :~: x)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, if we can find a Haskell term which has the above type we will have a
term such that given any &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt; and a proof of &lt;code&gt;x :~: y&lt;&#x2F;code&gt;, will return
a proof of &lt;code&gt;y :~: x&lt;&#x2F;code&gt;. If such term exists, it should be clear that the
proposition is true and thus we should accept that term as a proof! In
fact, this interpretation of a proof corresponds precisely to the BHK
interpretation. If you want to read more on the BHK interpretation I suggest
this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;plato.stanford.edu&#x2F;entries&#x2F;intuitionistic-logic-development&#x2F;#ProoInte&quot;&gt;Stanford Encyclopedia article&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;On we go to find a suitable term (proof)! We see that &lt;code&gt;(x :~: y) -&amp;gt; (y :~: x)&lt;&#x2F;code&gt;
is a function type with one argument, so a good place to start would be this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;sym :: (x :~: y) -&amp;gt; (y :~: x)
sym p = _
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we load this into ghci it will tell us that it has found a hole:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Found hole: _ :: y :~: x
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How can we fill this hole? Well, the only way to build something of type &lt;code&gt;y   :~: x&lt;&#x2F;code&gt; is by using the constructor &lt;code&gt;Refl&lt;&#x2F;code&gt;, but doing that would give us either
&lt;code&gt;x :~: x&lt;&#x2F;code&gt; or &lt;code&gt;y :~: y&lt;&#x2F;code&gt;, which is not what we want. So we are only left with
the option to pattern match against &lt;code&gt;p&lt;&#x2F;code&gt;. Here the type of the constructor
&lt;code&gt;Refl&lt;&#x2F;code&gt; will play a crucial role. Let&#x27;s proceed by asking ghci about its type.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ghci&amp;gt; :t Refl
ghci&amp;gt; Refl :: forall k (a :: k). a :~: a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What this says is: For any kind &lt;code&gt;k&lt;&#x2F;code&gt; and for any type &lt;code&gt;a&lt;&#x2F;code&gt; of kind &lt;code&gt;k&lt;&#x2F;code&gt; we have a
term of type &lt;code&gt;a :~: a&lt;&#x2F;code&gt;. We can think of a kind as the type of a type. I will
go back to types and kinds later in this section.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s reload the code after replacing &lt;code&gt;p&lt;&#x2F;code&gt; by &lt;code&gt;Refl&lt;&#x2F;code&gt;. Note
that I write &lt;code&gt;p@Refl&lt;&#x2F;code&gt; so it is easier for me to refer to this specific &lt;code&gt;Refl&lt;&#x2F;code&gt;
in the text, but we could simply drop &lt;code&gt;p@&lt;&#x2F;code&gt; to the same effect.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;sym :: (x :~: y) -&amp;gt; (y :~: x)
sym p@Refl = _
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we get that there is still a hole, but now it has type &lt;code&gt;x :~: x&lt;&#x2F;code&gt; instead
of &lt;code&gt;y :~: x&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Found hole: _ :: x :~: x
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We see that because of pattern matching and the type of &lt;code&gt;Refl&lt;&#x2F;code&gt;, GHC has
unified the type variables &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt;. Why? well, we know that before pattern
matching we had &lt;code&gt;p : x :~: y&lt;&#x2F;code&gt;. Then we have that &lt;code&gt;p@Refl : x :~: y&lt;&#x2F;code&gt;, and
therefore by the type of the constructor &lt;code&gt;Refl&lt;&#x2F;code&gt; it must be that &lt;code&gt;x ~ y&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Filling the hole and thus finishing the proof is trivial! We only need to
return the &lt;code&gt;Refl&lt;&#x2F;code&gt; constructor, which is a suitable term of the desired type &lt;code&gt;x   :~: x&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;sym :: (x :~: y) -&amp;gt; (y :~: x)
sym Refl = Refl
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yay! we finished our first proof! However, there is one critical condition for
a proof that we haven&#x27;t yet commented: termination. In the case of &lt;code&gt;sym&lt;&#x2F;code&gt;,
it obviously terminates for any input, since we just return the constructor
&lt;code&gt;Refl&lt;&#x2F;code&gt;. However, as proofs get more complicated and we need to perform
induction (as we will see in the &lt;a href=&quot;https:&#x2F;&#x2F;blog.janmasrovira.org&#x2F;blog&#x2F;dependent-haskell-proofs&#x2F;#proofs-on-natural-numbers&quot;&gt;natural numbers section&lt;&#x2F;a&gt;), it is easy to end up
writing a well typed term that will not terminate on some inputs. If a term
does not terminate on some inputs, then it obviously cannot be taken as a
proof. Unfortunately, we are on our own because GHC does not perform any kind
of termination checking for terms. As an example of a well typed but
non-terminating term consider the following definition:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;anyProof :: forall a. a
anyProof = anyProof
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, we should always be very careful not to introduce a non-terminating
(pseudo)proof, as the proof may be accepted by GHC and will lead us to believe
that we have proven something which may be false.&lt;&#x2F;p&gt;
&lt;p&gt;As a simple exercise, I propose that you try to prove that &lt;code&gt;:~:&lt;&#x2F;code&gt; is a
transitive relation. In Haskell terms, this means that you ought to find a
suitable definition for this type signature.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;trans :: (x :~: y) -&amp;gt; (y :~: z) -&amp;gt; (x :~: z)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Hint: The proof is really similar to the proof of &lt;code&gt;sym&lt;&#x2F;code&gt;&lt;&#x2F;em&gt;. After you have
proven this, you will have proven that &lt;code&gt;:~:&lt;&#x2F;code&gt; is symmetric, transitive and
reflexive (this property is given directly by the constructor &lt;code&gt;Refl&lt;&#x2F;code&gt;). Thus
you can conclude that &lt;code&gt;:~:&lt;&#x2F;code&gt; is an equivalence relation, which is the minimum
requirement a definition of equality should satisfy.&lt;&#x2F;p&gt;
&lt;p&gt;We end this section by summarizing the steps we should follow when writing a
proof in Haskell.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Write a type which represents the proposition that we want to prove.&lt;&#x2F;li&gt;
&lt;li&gt;Find a term that has that type. GHC makes sure that this step is correct
by type checking the term.&lt;&#x2F;li&gt;
&lt;li&gt;Make sure (outside of GHC&#x2F;in our meta reasoning) that the given term in the
previous step terminates for any input. If it doesn&#x27;t, we do not have a
valid proof.&lt;&#x2F;li&gt;
&lt;li&gt;Feel good.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;a-note-on-types-and-kinds&quot;&gt;A note on types and kinds&lt;&#x2F;h2&gt;
&lt;p&gt;This section is a small parenthesis on types and kinds. It is a bit technical
and tangential to the main topic so you may want to skip it on a first read.&lt;&#x2F;p&gt;
&lt;p&gt;If we inspect closely the type of &lt;code&gt;sym :: forall x y. (x :~: y) -&amp;gt; (y :~:    x)&lt;&#x2F;code&gt;, one may ask the questions: what are &lt;code&gt;x&lt;&#x2F;code&gt; and &lt;code&gt;y&lt;&#x2F;code&gt;? They are not defined
anywhere, yet we can use them? The answer lies in the fact that GHC types are
not fully explicit most of the time. Consider the identity function type:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;id :: a -&amp;gt; a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could have raised a similar question by looking at this type. If we rewrite
the previous type more explicitly, we would have:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;id :: forall a. a -&amp;gt; a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We see that we universally quantify a type variable &lt;code&gt;a&lt;&#x2F;code&gt;. But still this is not
fully explicit. One could ask: What is the type of &lt;code&gt;a&lt;&#x2F;code&gt;? Or in GHC terms, what
is the kind of &lt;code&gt;a&lt;&#x2F;code&gt;? Let&#x27;s rewrite the type to make it even more explicit.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;id :: forall k (a :: k). a -&amp;gt; a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ok, we have solved the problem for &lt;code&gt;a&lt;&#x2F;code&gt;. Now we know that &lt;code&gt;a&lt;&#x2F;code&gt; has kind &lt;code&gt;k&lt;&#x2F;code&gt;.
But what is the kind of &lt;code&gt;k&lt;&#x2F;code&gt;? We need to make it more explicit one last time.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;-- Type is imported from Data.Kind
id :: forall (k :: Type) (a :: k). a -&amp;gt; a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But how can it be that type of a kind &lt;code&gt;k&lt;&#x2F;code&gt; is &lt;code&gt;Type&lt;&#x2F;code&gt;? This is because in GHC
we have the axiom &lt;code&gt;Type :: Type&lt;&#x2F;code&gt;. This may raise some eyebrows since in the
field of logic typing relations which include at least a reflexive element,
such as &lt;code&gt;Type :: Type&lt;&#x2F;code&gt;, are well known to lead to inconsistent logics, and
thus are undesirable (if this topic is intriguing to you, I suggest that you
read the article on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;plato.stanford.edu&#x2F;entries&#x2F;russell-paradox&#x2F;&quot;&gt;Russell&#x27;s Paradox&lt;&#x2F;a&gt; in the Stanford Encyclopedia).
However, GHC allows &lt;code&gt;Type :: Type&lt;&#x2F;code&gt; because it has certain advantages. Moreover,
inconsistencies are present even without it. This makes sense because GHC is
not meant to be used as a proof assistant. In the paper &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.seas.upenn.edu&#x2F;~sweirich&#x2F;papers&#x2F;fckinds.pdf&quot;&gt;System FC with
Explicit Kind Equality&lt;&#x2F;a&gt;, Weirich, Hsu and Eisenberg argue that having the
&lt;code&gt;Type :: Type&lt;&#x2F;code&gt; axiom does not break GHC&#x27;s type system.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to know how the paradox has been avoided in a programming
language with dependent types, I suggest that you look into the Agda
documentation for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;agda.readthedocs.io&#x2F;en&#x2F;latest&#x2F;language&#x2F;universe-levels.html&quot;&gt;universe levels&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There is &lt;strong&gt;a lot&lt;&#x2F;strong&gt; more to types and kinds in GHC than what I have written (and
probably a significant portion escapes my knowledge at this point in time).
If you wish to know more, I suggest some references:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The paper &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.seas.upenn.edu&#x2F;~sweirich&#x2F;papers&#x2F;fckinds.pdf&quot;&gt;System FC with Explicit Kind Equality&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;GHC wiki article &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.haskell.org&#x2F;ghc&#x2F;ghc&#x2F;-&#x2F;wikis&#x2F;commentary&#x2F;compiler&#x2F;type-type&quot;&gt;type type&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Documentation for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;data_kinds.html&quot;&gt;&lt;code&gt;DataKinds&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Documentation for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;poly_kinds.html#extension-PolyKinds&quot;&gt;&lt;code&gt;PolyKinds&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Proposal for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.haskell.org&#x2F;ghc&#x2F;ghc&#x2F;-&#x2F;wikis&#x2F;unlifted-data-types&quot;&gt;unlifted data types&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;proofs-on-natural-numbers&quot;&gt;Proofs on natural numbers&lt;&#x2F;h1&gt;
&lt;p&gt;Finally something that is more tangible: natural numbers. As we know, a
natural numbers are the elements of the infinite sequence $0,1,2,3,…$. We will
begin by providing a Haskell inductive definition for them.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;data Nat where
  Zero :: Nat
  Suc :: Nat -&amp;gt; Nat
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can define particular naturals as expected:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;one :: Nat
one = Suc Zero

two :: Nat
two = Suc one
...
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Say that we want to prove that &lt;code&gt;one + one = two&lt;&#x2F;code&gt;. It should be pretty
straightforward right? Well, we have seen that we need to use types to express
propositions. But &lt;code&gt;one&lt;&#x2F;code&gt; and &lt;code&gt;two&lt;&#x2F;code&gt; are terms, so we can not use them in a type.
Moreover, how do we define addition on the type level?&lt;&#x2F;p&gt;
&lt;p&gt;In order to solve this problem we will use some help from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;data_kinds.html&quot;&gt;&lt;code&gt;DataKinds&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
extension. This extension promotes type constructors, such as &lt;code&gt;Nat&lt;&#x2F;code&gt;, to kinds.
Likewise, the extension promotes constructors, such as &lt;code&gt;Zero&lt;&#x2F;code&gt; and
&lt;code&gt;Suc&lt;&#x2F;code&gt;, to type constructors. Note that when we want to refer to a promoted
constructor we should prefix it with an apostrophe &lt;code&gt;&#x27;&lt;&#x2F;code&gt;. Now we can define
naturals on the type level thus:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;type One = &amp;#39;Suc &amp;#39;Zero
type Two = &amp;#39;Suc One
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first part of the problem is solved. We now need to define addition on the
promoted kind &lt;code&gt;Nat&lt;&#x2F;code&gt;. We can do so with the help of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;type_families.html&quot;&gt;&lt;code&gt;TypeFamilies&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;
extension. With this extension we can define &lt;em&gt;type families&lt;&#x2F;em&gt;, which
approximately are Haskell functions on types.&lt;&#x2F;p&gt;
&lt;p&gt;First let&#x27;s define addition on terms as we would normally do. This is only to
have a point of reference.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;(+) :: Nat -&amp;gt; Nat -&amp;gt; Nat where
Zero + b = b
(Suc a) + b = Suc (a + b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now see how we can translate the previous definition to type families.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;type family (a :: Nat) :+: (b :: Nat) :: Nat where
 &amp;#39;Zero :+: b = b
 &amp;#39;Suc a :+: b = &amp;#39;Suc (a :+: b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One can observe that both definitions look quite alike. In fact, they would be
exactly the same definition if we had full dependent types in GHC.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s try an example. Notice that the we need a &lt;code&gt;!&lt;&#x2F;code&gt; in &lt;code&gt;:k!&lt;&#x2F;code&gt; in order to ask
ghci to give us the normalized type.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ghci&amp;gt; :k! (&amp;#39;Suc &amp;#39;Zero) :+: (&amp;#39;Suc &amp;#39;Zero)
ghci&amp;gt; (&amp;#39;Suc &amp;#39;Zero) :+: (&amp;#39;Suc &amp;#39;Zero) :: Nat
ghci&amp;gt; = &amp;#39;Suc (&amp;#39;Suc &amp;#39;Zero)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Neat! We are finally ready to express in a type the property &lt;code&gt;one + one =   two&lt;&#x2F;code&gt; and prove it.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;onePlusOne :: (One :+: One) :~: Two
onePlusOne = Refl
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It suffices to use reflection since both types &lt;code&gt;One :+: One&lt;&#x2F;code&gt; and &lt;code&gt;Two&lt;&#x2F;code&gt;
normalize to &lt;code&gt;&#x27;Suc (&#x27;Suc &#x27;Zero)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s prove another property: &lt;code&gt;n + zero = n&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;nPlusZero :: (n :+: &amp;#39;Zero) :~: n
nPlusZero = Refl
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But now we get an error!&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Couldn&amp;#39;t match type ‘n’ with ‘n :+: &amp;#39;Zero’
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem is that &lt;code&gt;n :+: &#x27;Zero&lt;&#x2F;code&gt; cannot be normalized further. This is
because when we defined &lt;code&gt;:+:&lt;&#x2F;code&gt; we pattern matched the left argument, but now we
have &lt;code&gt;&#x27;Zero&lt;&#x2F;code&gt; on the right. Hence the expected way to proceed is to pattern match
on &lt;code&gt;n&lt;&#x2F;code&gt;. Unfortunately, we cannot pattern match on types directly so we
need to figure something out.&lt;&#x2F;p&gt;
&lt;p&gt;The strategy is to define a data type which will serve as a bridge between the
terms universe and the types universe.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;data SNat (n :: Nat) where
  SZero :: SNat &amp;#39;Zero
  SSuc :: SNat n -&amp;gt; SNat (&amp;#39;Suc n)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The new data type &lt;code&gt;SNat&lt;&#x2F;code&gt; which we just defined has the same structure as a
&lt;code&gt;Nat&lt;&#x2F;code&gt;, but it is indexed by a &lt;code&gt;Nat&lt;&#x2F;code&gt; on the type level. Note that the &lt;code&gt;n&lt;&#x2F;code&gt; in the
first line is &lt;strong&gt;not&lt;&#x2F;strong&gt; a term of type &lt;code&gt;Nat&lt;&#x2F;code&gt;. Instead, &lt;code&gt;n&lt;&#x2F;code&gt; is a type variable of
kind &lt;code&gt;Nat&lt;&#x2F;code&gt;. With the help of
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ghc.gitlab.haskell.org&#x2F;ghc&#x2F;doc&#x2F;users_guide&#x2F;exts&#x2F;gadt.html&quot;&gt;&lt;code&gt;GADTs&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, we
can use the promoted constructors &lt;code&gt;&#x27;Zero&lt;&#x2F;code&gt; and &lt;code&gt;&#x27;Suc&lt;&#x2F;code&gt; to create the desired link
between terms and types. The following theorem makes such a link explicit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Theorem&lt;&#x2F;strong&gt;. &lt;em&gt;For any type &lt;code&gt;n&lt;&#x2F;code&gt; of kind &lt;code&gt;Nat&lt;&#x2F;code&gt;, the type &lt;code&gt;SNat n&lt;&#x2F;code&gt; has exactly one term&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We prove it by induction on &lt;code&gt;n&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Base case &lt;code&gt;n&lt;&#x2F;code&gt; = &lt;code&gt;&#x27;Zero&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;By definition &lt;code&gt;SZero :: SNat &#x27;Zero&lt;&#x2F;code&gt;. To see that &lt;code&gt;SZero&lt;&#x2F;code&gt; is the only term of
type &lt;code&gt;SNat &#x27;Zero&lt;&#x2F;code&gt;, assume that there is a term &lt;code&gt;b :: SNat &#x27;Zero&lt;&#x2F;code&gt;. We
continue by cases on &lt;code&gt;b&lt;&#x2F;code&gt;. If &lt;code&gt;b&lt;&#x2F;code&gt; is &lt;code&gt;SZero&lt;&#x2F;code&gt; we are done. Otherwise &lt;code&gt;b&lt;&#x2F;code&gt; is of
the form &lt;code&gt;SSuc _&lt;&#x2F;code&gt;, but then &lt;code&gt;b&lt;&#x2F;code&gt;&#x27;s type must be of the form &lt;code&gt;SNat (&#x27;Suc _)&lt;&#x2F;code&gt;,
which is a contradiction.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Inductive case &lt;code&gt;n&lt;&#x2F;code&gt; = &lt;code&gt;&#x27;Suc m&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;By induction hypothesis we have that there exists exactly one term &lt;code&gt;i&lt;&#x2F;code&gt; such
that &lt;code&gt;i :: SNat m&lt;&#x2F;code&gt;. Then we have that &lt;code&gt;SSuc i :: SNat (&#x27;Suc m)&lt;&#x2F;code&gt;. Now assume
that there is a term &lt;code&gt;j :: SNat (&#x27;Suc m)&lt;&#x2F;code&gt;. From the type we know that &lt;code&gt;j&lt;&#x2F;code&gt; is
of the form &lt;code&gt;SSuc k&lt;&#x2F;code&gt; and &lt;code&gt;k :: SNat m&lt;&#x2F;code&gt;. Then by the induction hypothesis we
have that &lt;code&gt;i&lt;&#x2F;code&gt; = &lt;code&gt;k&lt;&#x2F;code&gt;. Therefore &lt;code&gt;j&lt;&#x2F;code&gt; = &lt;code&gt;SSuc i&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Qed.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Because of the previous property we call the type &lt;code&gt;SNat&lt;&#x2F;code&gt; a &lt;em&gt;singleton type&lt;&#x2F;em&gt;.
If you want a more extensive introduction to singleton types, I recommend &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.jle.im&#x2F;entry&#x2F;introduction-to-singletons-1.html&quot;&gt;this
blog&lt;&#x2F;a&gt; by Justin Le.&lt;&#x2F;p&gt;
&lt;p&gt;We can now use the singleton type &lt;code&gt;SNat&lt;&#x2F;code&gt; to pattern match on types of kind
&lt;code&gt;Nat&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;nPlusZero :: SNat n -&amp;gt; (n :+: &amp;#39;Zero) :~: n
nPlusZero SZero = _
nPlusZero (SSuc m) = _
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After loading the previous code into ghci we get the following information:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;For the base case (first hole):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Found hole: _ :: &amp;#39;Zero :~: &amp;#39;Zero
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This hole can be trivially proven with &lt;code&gt;Refl&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;For the inductive case (second hole):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Found hole: _ :: &amp;#39;Suc (n1 :+: &amp;#39;Zero) :~: &amp;#39;Suc n1
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We see that we need to prove an equality of the form &lt;code&gt;&#x27;Suc a :~: &#x27;Suc b&lt;&#x2F;code&gt;,
and this equality is implied by &lt;code&gt;a :~: b&lt;&#x2F;code&gt;. Let&#x27;s prove this fact as an
auxiliary lemma.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;congSuc :: a :~: b -&amp;gt; &amp;#39;Suc a :~: &amp;#39;Suc b
congSuc Refl = Refl
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We see that &lt;code&gt;congSuc&lt;&#x2F;code&gt; is a very simple lemma that can be proved in the same
way we proved &lt;code&gt;sym&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In order to use the previous lemma we only need to apply it as a regular
function.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;nPlusZero :: SNat n -&amp;gt; (n :+: &amp;#39;Zero) :~: n
nPlusZero SZero = Refl
nPlusZero (SSuc m) = congSuc _
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After applying &lt;code&gt;congSuc&lt;&#x2F;code&gt; the hole becomes:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Found hole: _ :: (n1 :+: &amp;#39;Zero) :~: n1
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It worked, the hole type became simpler! In fact, it looks much like the
property that we wanted to prove initially. This is often telling us that we
need to apply the induction hypothesis. Applying the induction hypothesis is
as simple as doing a recursive call to the theorem that we are proving.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;nPlusZero :: SNat n -&amp;gt; (n :+: &amp;#39;Zero) :~: n
nPlusZero SZero = Refl
nPlusZero (SSuc m) = congSuc (nPlusZero m)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We have finished our first proof by induction! Now imagine that we want to use
the previous theorem in another proof. In particular, imagine that we need to
fill a goal of type &lt;code&gt;SNat a -&amp;gt; SNat b -&amp;gt; (a :+: b) :+: &#x27;Zero&lt;&#x2F;code&gt;. It is clear
that the strategy should be to instantiate the &lt;code&gt;n&lt;&#x2F;code&gt; in the lemma &lt;code&gt;nPlusZero&lt;&#x2F;code&gt; as
&lt;code&gt;a :+: b&lt;&#x2F;code&gt;, but then we should provide an argument of type &lt;code&gt;SNat (a :+: b)&lt;&#x2F;code&gt;.
We can achieve that by implementing addition for the type &lt;code&gt;SNat&lt;&#x2F;code&gt; as follows.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;(.+.) :: SNat a -&amp;gt; SNat b -&amp;gt; SNat (a :+: b)
SZero .+. b    = b
SSuc a .+. b = SSuc (a .+. b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally we can use the theorem &lt;code&gt;nPlusZero&lt;&#x2F;code&gt; thus:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;someThm :: SNat a -&amp;gt; SNat b -&amp;gt; (a :+: b) :+: &amp;#39;Zero
someThm a b = nPlusZero (a .+. b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At this point I have given you
enough tools so that you can start writing your own proofs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;exercises&quot;&gt;Exercises&lt;&#x2F;h2&gt;
&lt;p&gt;Below I provide a list of theorems that you may want to prove as practice. If
you get stuck you can refer to my solutions in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;janmasrovira&#x2F;dependent-haskell&quot;&gt;this
repository&lt;&#x2F;a&gt;, specifically
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;janmasrovira&#x2F;dependent-haskell&#x2F;-&#x2F;blob&#x2F;master&#x2F;src&#x2F;Nats.hs&quot;&gt;this
file&lt;&#x2F;a&gt;.
I wrote these solutions about 3 years ago when I was still a complete novice at
writing proofs. So it is likely that you will find better proofs.&lt;&#x2F;p&gt;
&lt;p&gt;In order to solve the exercises you will need the following definitions.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;type family (a :: Nat) :*: (b :: Nat) :: Nat where
  &amp;#39;Zero :*: b = &amp;#39;Zero
  &amp;#39;Suc a :*: b = b :+: (a :*: b)

type family (a :: Nat) :^: (b :: Nat) :: Nat where
  a :^: &amp;#39;Zero = &amp;#39;Suc &amp;#39;Zero
  a :^: &amp;#39;Suc b = a :*: (a :^: b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Exercise list.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;plusSucR :: forall a b. SNat a -&amp;gt; SNat b -&amp;gt; (a :+: &amp;#39;Suc b) :~: &amp;#39;Suc (a :+: b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;plusAssoc :: forall a b c. SNat a -&amp;gt; SNat b -&amp;gt; SNat c -&amp;gt; (a :+: b) :+: c :~: a :+: (b :+: c)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;plusCommut :: forall a b. SNat a -&amp;gt; SNat b -&amp;gt; (a :+: b) :~: (b :+: a)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodZeroL :: SNat n -&amp;gt; &amp;#39;Zero :*: n :~: &amp;#39;Zero
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodZeroR :: SNat sn -&amp;gt; (sn :*: &amp;#39;Zero) :~: &amp;#39;Zero
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodOneL :: SNat sn -&amp;gt; (One :*: sn) :~: sn
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodOneR :: SNat sn -&amp;gt; (sn :*: One) :~: sn
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodSucL :: forall a b. SNat a -&amp;gt; SNat b -&amp;gt; (&amp;#39;Suc a :*: b) :~: b :+: (a :*: b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodSucR :: forall a b. SNat a -&amp;gt; SNat b -&amp;gt; (a :*: &amp;#39;Suc b) :~: a :+: (a :*: b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodDistribR :: forall a b c. SNat a -&amp;gt; SNat b -&amp;gt; SNat c 
    -&amp;gt; (a :+: b) :*: c :~: (a :*: c) :+: (b :*: c)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodDistribL :: forall a b c. SNat a -&amp;gt; SNat b -&amp;gt; SNat c -&amp;gt; 
   a :*: (b :+: c) :~: (a :*: b) :+: (a :*: c)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodAssoc :: forall a b c. SNat a -&amp;gt; SNat b -&amp;gt; SNat c 
    -&amp;gt; (a :*: b) :*: c :~: a :*: (b :*: c)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodCommut :: forall a b. SNat a -&amp;gt; SNat b -&amp;gt; (a :*: b) :~: (b :*: a)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;powerZero :: a :^: &amp;#39;Zero :~: One
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;powerOne :: SNat a -&amp;gt; a :^: One :~: a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;prodPower :: forall a b c. SNat a -&amp;gt; SNat b -&amp;gt; SNat c 
    -&amp;gt; (a :^: b) :*: (a :^: c) :~: a :^: (b :+: c)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;powerProd :: forall a b c. SNat a -&amp;gt; SNat b -&amp;gt; SNat c 
    -&amp;gt; (a :^: c) :*: (b :^: c) :~: (a :*: b) :^: c
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;proofs-on-lists&quot;&gt;Proofs on lists&lt;&#x2F;h1&gt;
&lt;p&gt;More exercises for lists.&lt;&#x2F;p&gt;
&lt;p&gt;You will need some common functions on lists on the type level.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;type family Length (l :: [*]) :: Nat where
  Length &amp;#39;[] = &amp;#39;Zero
  Length (_&amp;#39;:r) = &amp;#39;Suc (Length r)

type family (a :: [*]) :++: (b :: [*]) :: [*] where
  &amp;#39;[] :++: b = b
  (a &amp;#39;: as) :++: b = a : (as :++: b)

type family Reverse (a :: [*]) :: [*] where
  Reverse &amp;#39;[] = &amp;#39;[]
  Reverse (a &amp;#39;: as) = Reverse as :++: &amp;#39;[a]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A singleton list type can be defined thus:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;data HList (l :: [*]) :: * where
  HNil :: HList &amp;#39;[]
  HCons :: t -&amp;gt; HList l -&amp;gt; HList (t &amp;#39;: l)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;List of exercises.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;concatNilL :: &amp;#39;[] :++: a :~:  a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;concatNilR :: HList a -&amp;gt; a :++: &amp;#39;[] :~: a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;lengthCons :: HList a -&amp;gt; Length (t &amp;#39;: a) :~: &amp;#39;Suc (Length a)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;lengthConcat :: HList a -&amp;gt; HList b -&amp;gt; Length a :+: Length b :~: Length (a :++: b)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;concatAssoc :: forall a b c.  HList a -&amp;gt; HList b -&amp;gt; HList c
    -&amp;gt; (a :++: b) :++: c :~: a :++: (b :++: c)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;lengthConcatCommut :: forall a b. HList a -&amp;gt; HList b
    -&amp;gt; Length (a :++: b) :~: Length (b :++: a)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;lengthReverse :: HList a -&amp;gt; Length (Reverse a) :~: Length a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;concatReverse :: forall a b . HList a -&amp;gt; HList b
    -&amp;gt; Reverse a :++: Reverse b :~: Reverse (b :++: a)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;consReverse :: forall a t. HList a -&amp;gt; t &amp;#39;: Reverse a :~: Reverse (a :++: &amp;#39;[t])
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;reverseReverse :: forall a. HList a -&amp;gt; Reverse (Reverse a) :~: a
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;singletons-library&quot;&gt;Singletons library&lt;&#x2F;h1&gt;
&lt;p&gt;If you plan on using singleton types on your projects, you should definitely
look into the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hackage.haskell.org&#x2F;package&#x2F;singletons&quot;&gt;&lt;code&gt;singletons&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library. According to its documentation,
&lt;em&gt;&lt;code&gt;singletons&lt;&#x2F;code&gt; contains the basic types and definitions needed to support
dependently typed programming techniques in Haskell.&lt;&#x2F;em&gt; Additionally, it is very
convenient to combine it with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hackage.haskell.org&#x2F;package&#x2F;singletons-th&quot;&gt;&lt;code&gt;singletons-th&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; library, which will
automatically generate a lot of boilerplate code for you. For instance, in
order to define the natural numbers we needed to define &lt;code&gt;Nat&lt;&#x2F;code&gt; and &lt;code&gt;SNat&lt;&#x2F;code&gt;. The
latter can be automatically generated by &lt;code&gt;singletons-th&lt;&#x2F;code&gt;. Moreover, when
defining addition we needed to define &lt;code&gt;:+:&lt;&#x2F;code&gt; on the type level for the kind
&lt;code&gt;Nat&lt;&#x2F;code&gt; and &lt;code&gt;.+.&lt;&#x2F;code&gt; on the singleton term level for &lt;code&gt;SNat&lt;&#x2F;code&gt;. Again, with the
&lt;code&gt;singletons-th&lt;&#x2F;code&gt; library, we could automatically generate both &lt;code&gt;:+:&lt;&#x2F;code&gt; and &lt;code&gt;.+.&lt;&#x2F;code&gt;
from the simple definition of &lt;code&gt;+&lt;&#x2F;code&gt; on the type &lt;code&gt;Nat&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Giving a detailed introduction to the &lt;code&gt;singletons&lt;&#x2F;code&gt; library is out of the scope
of this blog. For that, I recommend the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;goldfirere&#x2F;singletons&#x2F;blob&#x2F;master&#x2F;README.md&quot;&gt;&lt;code&gt;Readme&lt;&#x2F;code&gt; of the &lt;code&gt;singletons&lt;&#x2F;code&gt; library&lt;&#x2F;a&gt;
and (again) &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.jle.im&#x2F;entry&#x2F;introduction-to-singletons-1.html&quot;&gt;this blog&lt;&#x2F;a&gt; by Justin Le.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;useful-references&quot;&gt;Useful references&lt;&#x2F;h1&gt;
&lt;p&gt;If you want to know more or you want different takes on this topic, I would
suggest that you look into these references.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lexi-lambda.github.io&#x2F;blog&#x2F;2021&#x2F;03&#x2F;25&#x2F;an-introduction-to-typeclass-metaprogramming&#x2F;&quot;&gt;An introduction to typeclass metaprogramming&lt;&#x2F;a&gt; by Alexis King.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;channel&#x2F;UCI1Z201n-8OelkSg0DVOsng&quot;&gt;Tweag youtube channel&lt;&#x2F;a&gt; featuring Richard Eisenberg.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.parsonsmatt.org&#x2F;2017&#x2F;04&#x2F;26&#x2F;basic_type_level_programming_in_haskell.html&quot;&gt;Basic Type Level Programming in Haskell&lt;&#x2F;a&gt; by Matt Parsons.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ncatlab.org&#x2F;nlab&#x2F;show&#x2F;propositions+as+types&quot;&gt;nLab: propositions as types&lt;&#x2F;a&gt; (not Haskell, more theoretical).&lt;&#x2F;li&gt;
&lt;li&gt;If you know of a nice reference which is missing here, let me know and I&#x27;ll
add it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;final-words&quot;&gt;Final words&lt;&#x2F;h1&gt;
&lt;p&gt;I hope you found this interesting. If you find any mistake, please let me know.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Run-length encoding verified in Agda</title>
        <published>2019-09-07T00:00:00+00:00</published>
        <updated>2019-09-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.janmasrovira.org/blog/rle/"/>
        <id>https://blog.janmasrovira.org/blog/rle/</id>
        
        <content type="html" xml:base="https://blog.janmasrovira.org/blog/rle/">&lt;p&gt;This post is intended to be a guided exercise (with a proposed solution) for
Agda beginner&#x27;s who are familiar with the basics and want to work on a slightly
more involved exercise than proving basic properties about natural numbers. By
&lt;em&gt;verified algorithm&lt;&#x2F;em&gt; we mean that termination is guaranteed and that it produces
the right output. In our case we want the compression and decompression
functions to satisfy $decompress ∘ compress = id$. Termination is automatically
checked by Agda so it will not require an explicit proof.&lt;&#x2F;p&gt;
&lt;p&gt;The full code is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;snippets&#x2F;1893023&quot;&gt;here&lt;&#x2F;a&gt; (spoilers!). Agda 2.6.0.1 was used.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-algorithm&quot;&gt;The algorithm&lt;&#x2F;h1&gt;
&lt;p&gt;The run-length encoding algorithm (RLE for short) is the most basic lossless
compression algorithm one could imagine. The algorithm goes through the string
and groups consecutive characters by saving just one character and the length
of the group. For instance, the string &lt;code&gt;aaabbcccc&lt;&#x2F;code&gt; becomes &lt;code&gt;(3,a)(2,b)(4,c)&lt;&#x2F;code&gt;.
Notice that parentheses and commas are used to denote pairs and not literal
characters of the string. Finally, by looking at the compressed string the
decompression algorithm is immediately apparent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementation&quot;&gt;Implementation&lt;&#x2F;h2&gt;
&lt;p&gt;The proposed implementation uses some basic functions from the standard
library. Here is a full list of the needed types and function imports for the
implementation. If you are not familiar with them, you should refer to the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agda&#x2F;agda-stdlib&quot;&gt;standard library&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;open import Agda.Builtin.Nat using (Nat; zero; suc)
open import Data.List using (List; []; _∷_; replicate; _++_; foldl)
open import Data.Maybe using (Maybe; just; nothing)
open import Data.Nat.Properties using (_≟_)
open import Data.Product using (_×_; _,_; proj₁; proj₂)
open import Relation.Nullary using (yes; no)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this post we will not delve in low level details such as how to encode pairs
or using machine bytes, instead, we will use naturals as bytes and lists of
naturals as byte strings.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Byte : Set
Byte = Nat

ByteString : Set
ByteString = List Byte
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;the-exercises&quot;&gt;The exercises&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;compression-algorithm&quot;&gt;Compression algorithm&lt;&#x2F;h3&gt;
&lt;p&gt;Implement the compression algorithm:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;compress-rle : ByteString → List (Nat × Byte)
compress-rle = ?
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Implementing this algorithm in a language such as Haskell is trivial, however,
in Agda it can be a little bit trickier due the termination checker.&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;Proposed solution&lt;&#x2F;summary&gt;
&lt;pre&gt;&lt;code&gt;rle : Maybe (Nat × Byte) → ByteString → List (Nat × Byte) → List (Nat × Byte)
rle nothing [] ac = ac
rle (just (k , b)) [] ac = (k , b) ∷ ac
rle nothing (x ∷ tail) ac = rle (just (1 , x)) tail ac
rle (just (k , b)) (x ∷ tail) ac with b ≟ x
... | yes p = rle ((just (suc k , b))) tail ac
... | no p = rle (just (1 , x)) tail ((k , b) ∷ ac)

compress-rle : ByteString → List (Nat × Byte)
compress-rle l = rle nothing l []
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;h3 id=&quot;decompression-algorithm&quot;&gt;Decompression algorithm&lt;&#x2F;h3&gt;
&lt;p&gt;Implement the decompression algorithm:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;decompress-rle : List (Nat × Byte) → ByteString
decompress-rle = ?
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;details&gt;
&lt;summary&gt;Proposed solution&lt;&#x2F;summary&gt;
&lt;pre&gt;&lt;code&gt;dec-step : ByteString → (Nat × Byte) → ByteString
dec-step = λ ac y → replicate (proj₁ y) (proj₂ y) ++ ac

decompress-rle : List (Nat × Byte) → ByteString
decompress-rle = foldl dec-step []
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;h1 id=&quot;verification&quot;&gt;Verification&lt;&#x2F;h1&gt;
&lt;p&gt;The goal of this section is to provide a proof (term) of the following theorem (type):&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;inverse-rle : ∀ b → decompress-rle (compress-rle b) ≡ b
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The proof will indeed depend on the implementation, so if you want to follow
along you should use the proposed code above.&lt;&#x2F;p&gt;
&lt;p&gt;The proof is not straightforward, so in order to guide the reader we suggest
three lemmas that will lead to the proof. Of course, these lemmas
are not required and you may want to take another road to prove the theorem.&lt;&#x2F;p&gt;
&lt;p&gt;We also suggest that you add the following imports:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;open import Data.List.Properties using (++-identityʳ; ++-assoc)
open import Relation.Binary.PropositionalEquality using (_≡_; refl; sym; trans)
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;lemma-1&quot;&gt;Lemma 1&lt;&#x2F;h3&gt;
&lt;p&gt;Prove the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;decompress-head : ∀ (l k x) → decompress-rle ((k , x) ∷ l) ≡ decompress-rle l ++ replicate k x
decompress-head = ?
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;details&gt;
&lt;summary class=&quot;alert page-subtitle&quot;&gt;Proposed solution&lt;&#x2F;summary&gt;
&lt;pre&gt;&lt;code&gt;decompress-head : ∀ (l k x) → decompress-rle ((k , x) ∷ l) ≡ decompress-rle l ++ replicate k x
decompress-head l k x = trans s1 (s2 l [] k x)
  where
  s1 : decompress-rle ((k , x) ∷ l) ≡ foldl dec-step (replicate k x) l
  s1 rewrite ++-identityʳ (replicate k x) = refl
  s2 : ∀ l ac k x → foldl dec-step (ac ++ replicate k x) l ≡ foldl dec-step ac l ++ replicate k x
  s2 [] ac k x = refl
  s2 ((k1 , x1) ∷ l) ac k x rewrite
      ++-identityʳ (replicate k1 x1)
      | sym (s2 l (replicate k1 x1 ++ ac) k x)
      | ++-assoc (replicate k1 x1) ac (replicate k x)
    = refl
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;&#x2F;div&gt;
&lt;h3 id=&quot;lemma-2&quot;&gt;Lemma 2&lt;&#x2F;h3&gt;
&lt;p&gt;Prove the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;decompress-just : ∀ (k x bs l) → decompress-rle (rle (just (k , x)) bs l) ≡ decompress-rle l ++ (replicate k x ++ bs)
decompress-just = ?
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;details&gt;
&lt;summary&gt;Proposed solution&lt;&#x2F;summary&gt;
&lt;pre&gt;&lt;code&gt;lemma-replicate : ∀ (bs k) (x : Byte) → x ∷ replicate k x ++ bs ≡ replicate k x ++ x ∷ bs
lemma-replicate bs zero x = refl
lemma-replicate bs (suc k) x rewrite lemma-replicate bs k x = refl

decompress-just : ∀ (k x bs l) → decompress-rle (rle (just (k , x)) bs l) ≡ decompress-rle l ++ (replicate k x ++ bs)
decompress-just k x [] l rewrite
   ++-identityʳ (replicate k x)
   | sym (decompress-head l k x)
   | ++-identityʳ (replicate k x)
   = refl
decompress-just k x (y ∷ bs) ac with x ≟ y
... | yes refl rewrite
  decompress-just (suc k) x bs ac
  | lemma-replicate bs k x
  = refl
... | no _ rewrite
  decompress-just 1 y bs ((k , x) ∷ ac)
  | ++-identityʳ (replicate k x)
  | sym (++-assoc (foldl dec-step [] ac) (replicate k x) (y ∷ bs))
  | sym (decompress-head ac k x)
  | ++-identityʳ (replicate k x)
  = refl
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;h3 id=&quot;lemma-3&quot;&gt;Lemma 3&lt;&#x2F;h3&gt;
&lt;p&gt;Prove the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;decompress-nothing : ∀ (b ac) → decompress-rle (rle nothing b ac) ≡ decompress-rle ac ++ b
decompress-nothing = ?
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;details&gt;
&lt;summary&gt;Proposed solution&lt;&#x2F;summary&gt;
&lt;pre&gt;&lt;code&gt;decompress-nothing : ∀ (b ac) → decompress-rle (rle nothing b ac) ≡ decompress-rle ac ++ b
decompress-nothing [] [] = refl
decompress-nothing [] (x ∷ ac) =  sym (++-identityʳ (decompress-rle (x ∷ ac)))
decompress-nothing (x ∷ b) ac = decompress-just 1 x b ac
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;h2 id=&quot;main-theorem&quot;&gt;Main theorem&lt;&#x2F;h2&gt;
&lt;p&gt;With the lemma 3 in hand, it should be trivial to prove the main theorem.&lt;&#x2F;p&gt;
&lt;p&gt;Prove the following:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;inverse-rle : ∀ b → decompress-rle (compress-rle b) ≡ b
inverse-rle = ?
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;details&gt;
&lt;summary&gt;Proposed solution&lt;&#x2F;summary&gt;
&lt;pre&gt;&lt;code&gt;inverse-rle : ∀ b → decompress-rle (compress-rle b) ≡ b
inverse-rle b = decompress-nothing b []
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;details&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h1&gt;
&lt;p&gt;We have implemented and verified the run-length encoding algorithm in Agda and
we have seen that even a simple algorithm is not straightforward to verify.&lt;&#x2F;p&gt;
&lt;p&gt;I am sure that the proposed proof is not the most concise and I think that it
would be a good exercise to try to improve it.&lt;&#x2F;p&gt;
&lt;p&gt;Suggestions are welcome!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>An Agda eDSL for well-typed Hilbert style proofs</title>
        <published>2019-05-19T00:00:00+00:00</published>
        <updated>2019-05-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.janmasrovira.org/blog/hilbert-edsl/"/>
        <id>https://blog.janmasrovira.org/blog/hilbert-edsl/</id>
        
        <content type="html" xml:base="https://blog.janmasrovira.org/blog/hilbert-edsl/">&lt;p&gt;I present an Agda eDSL for writing Hilbert style proofs for logic $𝑲$.&lt;&#x2F;p&gt;
&lt;p&gt;This blog consists of two main parts. The first part presents the language and
some examples. The second offers some insight into the key parts of the
implementation. The latter targets Agda beginner&#x2F;intermediate users or any
programmer interested in dependent types.&lt;&#x2F;p&gt;
&lt;p&gt;The code is available &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;snippets&#x2F;1858322&quot;&gt;here&lt;&#x2F;a&gt;. It has been implemented using Agda 2.6.0 with the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agda&#x2F;agda-stdlib&quot;&gt;standard library&lt;&#x2F;a&gt; (at this specific &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agda&#x2F;agda-stdlib&#x2F;commit&#x2F;805c897f32f605a666ec3738a3005e3800bf2964&quot;&gt;commit&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-introductory-concepts&quot;&gt;Some introductory concepts&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;What is an eDSL?&lt;&#x2F;strong&gt; The acronym eDSL stands for Embedded Domain Specific
Language. It refers to a small language (a set of functions and data types)
embedded in another language (in this case Agda) that has been designed to
solve a problem in a very specific domain, in this case, Hilbert style proofs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What is a Hilbert style proof?&lt;&#x2F;strong&gt; First we need to know what a Hilbert calculus
is. A Hilbert calculus is a set of axioms plus a set of rules. The axioms are
formulas that we accept as primitive theorems and the rules allow us to
syntactically combine existing theorems to create new ones. Then, a Hilbert
style proof is a sequence of formulas where each formula is either an axiom of
the calculus or the result of applying a rule to previous formulas in the
sequence. The last formula in the sequence is the theorem of the proof. It is
best understood by seeing a concrete example, if you scroll down you will find
one.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-edsl-and-logic-k&quot;&gt;The eDSL and logic $K$&lt;&#x2F;h1&gt;
&lt;p&gt;As a preface, let me remark that that the chosen logic, $𝑲$, is not of
special importance here, it just lays the ground for some concrete examples.
In fact, it would be interesting to implement a logic agnostic eDSL in
the future.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s begin by defining the syntax of modal formulas:&lt;&#x2F;p&gt;
&lt;p&gt;\[
\begin{align*}
ModalFm ≔ Var\ |\ ModalFm → ModalFm\ |\ □ ModalFm \ |\ ⊥   \\
\end{align*}
\]&lt;&#x2F;p&gt;
&lt;p&gt;Of course, we are missing important logical connectives like $¬,∧,∨$, but it
is better to have a small core language and define the other connectives in
terms of the primitive ones, for instance:&lt;&#x2F;p&gt;
&lt;p&gt;\[
\begin{align*}
¬ϕ &amp;amp; ≔ ϕ→⊥ \\
ϕ∧ψ &amp;amp; ≔ ¬(ϕ→¬ψ) \\
ϕ∨ψ &amp;amp; ≔ ¬ϕ→ψ \\
\end{align*}
\]&lt;&#x2F;p&gt;
&lt;p&gt;The axioms of $𝑲$ are the following:&lt;&#x2F;p&gt;
&lt;p&gt;\[
\begin{align*}
\text{(K1)  } &amp;amp; ϕ → (ψ → ϕ) \\
\text{(K2)  } &amp;amp; (ϕ → (ψ → ξ)) → ((ϕ → ψ) → (ϕ → ξ)) \\
\text{(K3)  } &amp;amp; (¬ ϕ → ¬ ψ) → (ψ → ϕ) \\
\text{(Distribution)  } &amp;amp; □ (ϕ → ψ) → (□ ϕ → □ ψ)
\end{align*}
\]&lt;&#x2F;p&gt;
&lt;p&gt;The above are axiom schemes (or templates), so $ϕ,ψ,ζ$ are
formula metavariables which can be substituted for any modal formula.&lt;&#x2F;p&gt;
&lt;p&gt;And the rules are the following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modus Ponens:&lt;&#x2F;strong&gt; If $ϕ$ is a theorem and $ϕ→ψ$ is a theorem, then $ψ$
is a theorem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;\[
\begin{array}{c}
ϕ→ψ \\
ϕ \\
\hline
ψ
\end{array}
\]&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Necessitation:&lt;&#x2F;strong&gt; If $ϕ$ is a theorem then $□ϕ$ is a theorem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;\[
\begin{array}{c}
ϕ \\
\hline
□ϕ
\end{array}
\]&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Identity:&lt;&#x2F;strong&gt; If $ϕ∈Σ$ then $Σ⊢ϕ$. Note that $ϕ$ may not be a theorem. See
clarification at the end of this section.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Finally! we can construct our first Hilbert style proof. Let’s prove $□(ϕ→ϕ)$.&lt;&#x2F;p&gt;
&lt;p&gt;\[
\begin{array}{lr}
\text{[ 0 ] } (ϕ → ((ϕ → ϕ) → ϕ)) → ((ϕ → (ϕ → ϕ)) → (ϕ → ϕ))  &amp;amp; \text{By K2} \\
\text{[ 1 ] }  ϕ → ((ϕ → ϕ) → ϕ)                                &amp;amp; \text{By K1} \\
\text{[ 2 ] }  ϕ → (ϕ → ϕ)                                        &amp;amp; \text{By K1} \\
\text{[ 3 ] } (ϕ → (ϕ → ϕ)) → (ϕ → ϕ)                           &amp;amp; \text{By MP 0,  1} \\
\text{[ 4 ] } ϕ → ϕ                                             &amp;amp; \text{By MP 3, 2} \\
\text{[ 5 ] } □ (ϕ → ϕ)                                         &amp;amp; \text{By Nec 4}\\
\end{array}
\]&lt;&#x2F;p&gt;
&lt;p&gt;And now… how does the same proof look in our eDSL as Agda code? Here it is:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;□⟨ϕ↝ϕ⟩ : ∀ {Σ ϕ} → Σ ⊢ □ (ϕ ↝ ϕ)
□⟨ϕ↝ϕ⟩ {Σ} {ϕ} =
  begin[ 0 ] (ϕ ↝ ((ϕ ↝ ϕ) ↝ ϕ)) ↝ ((ϕ ↝ (ϕ ↝ ϕ)) ↝ (ϕ ↝ ϕ)) By K2
       [ 1 ] ϕ ↝ ((ϕ ↝ ϕ) ↝ ϕ)                               By K1
       [ 2 ] ϕ ↝ (ϕ ↝ ϕ)                                      By K1
       [ 3 ] (ϕ ↝ (ϕ ↝ ϕ)) ↝ (ϕ ↝ ϕ)                        ByMP 0 , 1
       [ 4 ] ϕ ↝ ϕ                                             ByMP 3 , 2
       [ 5 ] □ (ϕ ↝ ϕ)                                         ByNec 4
       ■
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wow, they look really similar indeed! So what? Well, we can write Hilbert styles
proofs in a paper-like syntax with the key advantage that Agda’s type
checker will make sure that the proof is constructed according to the rules,
that is, that there are &lt;strong&gt;no mistakes&lt;&#x2F;strong&gt; in it. For instance, proofs where an axiom
is instantiated incorrectly, or an application of modus ponens is incorrect will
fail to type check and we will get an error from the compiler telling us where
the misstep is. An additional free perk that we get is that we can easily export the proofs to
rich &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;agda.readthedocs.io&#x2F;en&#x2F;latest&#x2F;tools&#x2F;generating-html.html&quot;&gt;html&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;agda.readthedocs.io&#x2F;en&#x2F;latest&#x2F;tools&#x2F;generating-latex.html&quot;&gt;latex&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let me underline that the code above is actual Agda code. This might be
surprising for readers not accustomed to Agda’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;agda.readthedocs.io&#x2F;en&#x2F;v2.6.0&#x2F;language&#x2F;mixfix-operators.html&quot;&gt;mixfix operators&lt;&#x2F;a&gt;, which give
great syntactical versatility.&lt;&#x2F;p&gt;
&lt;p&gt;It is worth noting that the &lt;code&gt;By&lt;&#x2F;code&gt; step does not only accept axioms, but any
theorem previously proved. So, if we were to prove another theorem and we wanted
to use $□ (ϕ → ϕ)$ as an intermediate step we could do so. Also, since we proved
$□(ϕ→ϕ)$ for any $ϕ$, we are free to substitute it for any formula. Example:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;...
[ 1 ] □ (ϕ ↝ ϕ)             By □⟨ϕ↝ϕ⟩
[ 2 ] □ ((ψ ∧ ϕ) ↝ (ψ ∧ ϕ)) By □⟨ϕ↝ϕ⟩
...
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What about premises? Well, as you may have already noticed in the previous
proof, we wrote $Σ ⊢ □ (ϕ → ϕ)$, where $Σ$ is our set of premises, and we are
free to use any formula in $Σ$ as if it was a theorem within the proof.
As an example, let’s prove $ϕ→ψ,ϕ,Σ⊢ψ$.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ϕ↝ψ∷ϕ∷Σ⊢ψ : ∀ {ϕ ψ Σ} → ϕ ↝ ψ ∷ ϕ ∷ Σ ⊢ ψ
ϕ↝ψ∷ϕ∷Σ⊢ψ {ϕ} {ψ} =
  begin[ 0 ] ϕ       By premise 1
       [ 1 ] ϕ ↝ ψ   By premise 0
       [ 2 ] ψ       ByMP 0 , 1
       ■
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Clarification:&lt;&#x2F;strong&gt; Notice that a formula $ϕ$ is a &lt;em&gt;theorem&lt;&#x2F;em&gt; of the
logic $K$ if and only if $∅⊢ϕ$. So in case we have $Σ⊢ϕ$ with $Σ$ nonempty it
may be that $ϕ$ is not a theorem of $K$. It is worth noting that when we
define &lt;code&gt;ϕ↝ϕ : ∀ {Σ ϕ} : Σ ⊢ ϕ ↝ ϕ&lt;&#x2F;code&gt;, then the term &lt;code&gt;ϕ↝ϕ&lt;&#x2F;code&gt; is really a proof that
$ϕ → ϕ$ is a theorem of $K$ since $Σ$ is a parameter of the proof and in
particular it can be empty.&lt;&#x2F;p&gt;
&lt;p&gt;This concludes the overview of the language features.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;implementation-tour&quot;&gt;Implementation tour&lt;&#x2F;h1&gt;
&lt;p&gt;We start by defining the syntax of formulas. We define variables to be
natural numbers but this is not really relevant.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;Var : Set
Var = Nat

infixr 20 _↝_
data Fm : Set where
  _! : Var → Fm
  _↝_ : Fm → Fm → Fm
  □ : Fm → Fm
  ⊥ : Fm
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, if we wanted, we could expand our language by defining more function
symbols. For instance, we could define negation thus:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;¬ : Fm → Fm
¬ ϕ = ϕ ↝ ⊥
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could do the same for $∧,∨,♢,⊤$ and any other operator.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s define a data type that represents a proof in Hilbert calculus. As
expected, it will have a constructor for each axiom scheme and rule.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;infix 0 _⊢_
data _⊢_ (Σ : List Fm) : Fm → Set where
  K1 : ∀ {ϕ ψ : Fm} → Σ ⊢ ϕ ↝ (ψ ↝ ϕ)
  K2 : ∀ {ϕ ψ ξ : Fm} → Σ ⊢ (ϕ ↝ (ψ ↝ ξ)) ↝ ((ϕ ↝ ψ) ↝ (ϕ ↝ ξ))
  K3 : ∀ {ϕ ψ : Fm} → Σ ⊢ (¬ ϕ ↝ ¬ ψ) ↝ (ψ ↝ ϕ)
  distribution : {ϕ ψ : Fm} → Σ ⊢ □ (ϕ ↝ ψ) ↝ (□ ϕ ↝ □ ψ)
  necessitation : ∀ {ϕ : Fm} → Σ ⊢ ϕ → Σ ⊢ □ ϕ
  mp : ∀ {ϕ ψ : Fm} → Σ ⊢ (ϕ ↝ ψ) → Σ ⊢ ϕ → Σ ⊢ ψ
  premise : ∀ {ϕ : Fm} → Member ϕ Σ → Σ ⊢ ϕ
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now write our first proof. The following proof corresponds to the proof
that $ϕ→ϕ$ is a theorem of $K$ shown above.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ϕ↝ϕ : ∀ {Σ ϕ} → Σ ⊢ (ϕ ↝ ϕ)
ϕ↝ϕ {Σ} {ϕ} = mp (mp (K2 {Σ} {ϕ} {ϕ ↝ ϕ} {ϕ}) (K1 {Σ} {ϕ} {ϕ ↝ ϕ})) (K1 {Σ} {ϕ} {ϕ})
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is horrible to read and too verbose. We can make it a little more succinct by
taking advantage of Agda’s implicit argument inference:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;ϕ↝ϕ : ∀ {Σ ϕ} → Σ ⊢ ϕ ↝ ϕ
ϕ↝ϕ {Σ} {ϕ} = mp (mp K2 K1) (K1 {ψ = ϕ})
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Much better but still hard for a human to visualize what are the intermediate
steps. Computer programmers could think of this as machine code; something
very useful for its simplicity but hard for humans to use. So, as we do in
programming, we will design a human-friendly language and a compiler that
translates nice looking proofs into (let’s call them) &lt;em&gt;primitive Hilbert style
proofs&lt;&#x2F;em&gt;. Of course, everything will be guaranteed to work from the types, so
no need to execute any code, just type check it (as is always the case when
using Agda as a proof checker).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-sketch-of-the-edsl&quot;&gt;A sketch of the eDSL&lt;&#x2F;h2&gt;
&lt;p&gt;We want a language as close to the paper-like syntax showed above as
possible. We will refer to proofs in this language as &lt;em&gt;nice proofs&lt;&#x2F;em&gt; and
proofs of the type &lt;code&gt;_⊢_&lt;&#x2F;code&gt; as &lt;em&gt;primitive proofs&lt;&#x2F;em&gt;. We will refer to the
process of translating nice proofs to primitive proofs as &lt;em&gt;compilation&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First we need to think about the type of a nice proof. Well, it needs to keep
track of the set of premises, the formula that entails and the length of it,
so the following type is what we want.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;data HilbertProof : List Fm → Fm → Nat → Set
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then the compile function will be of the following type.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;compile : ∀ {n Σ ϕ} → HilbertProof Σ ϕ n → Σ ⊢ ϕ
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now think about which constructors we need for a nice proof.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;By&lt;&#x2F;code&gt;. To reference an axiom or another theorem.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;MP&lt;&#x2F;code&gt;. To apply modus ponens to previous formulas in the proof.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Nec&lt;&#x2F;code&gt;. To apply necessitation to a previous formula in the proof.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We will refer to these constructors as &lt;em&gt;instructions&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Instructions are numbered with consecutive naturals starting at 0. This
number is used to reference its corresponding formula in subsequent steps.
There must be a special instruction that does not expect instructions before
it. We call this instruction &lt;code&gt;Begin&lt;&#x2F;code&gt; and it works the same as &lt;code&gt;By&lt;&#x2F;code&gt; with the
exception that it can only be used as the first instruction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;highlights&quot;&gt;Highlights&lt;&#x2F;h2&gt;
&lt;p&gt;We face the following challenges.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Numbering&lt;&#x2F;strong&gt;. We need to make sure that the user labels the instructions
properly.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Proper references&lt;&#x2F;strong&gt;. We need to make sure that the numbers referencing
other instructions are in range of the size of the proof and that
they reference the appropriate formulas.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Compilation&lt;&#x2F;strong&gt;. We need to translate nice proofs into primitive proofs.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;numbering&quot;&gt;Numbering&lt;&#x2F;h3&gt;
&lt;p&gt;The numbering certainly looks easier to tackle, so let’s start by this one.
Instead of trying to solve our problem directly, I propose an alternative
problem that captures the same challenge but with no unnecessary noise around it.&lt;&#x2F;p&gt;
&lt;div class=&quot;alert alert-note&quot;&gt;&lt;p class=&quot;alert page-subtitle&quot;&gt;Exercise: Boring list&lt;&#x2F;p&gt;
&lt;p&gt;Define a list type such that the first number must be a zero and
each subsequent number must be equal to the head plus one.&lt;&#x2F;p&gt;
&lt;details class=&quot;alert alert-success&quot;&gt;
&lt;summary class=&quot;page-subtitle&quot;&gt;Solution&lt;&#x2F;summary&gt;
&lt;p&gt;We do so with the help of singleton types.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;data SingleNat : Nat → Set where
  single : (n : Nat) → SingleNat n

data BoringList : Nat → Set where
  [_] : SingleNat 0 → BoringList 0
  _∷_ : ∀ {n} → SingleNat (suc n) → BoringList n → BoringList (suc n)

example : BoringList 2
example = single 2 ∷ (single 1 ∷ [ single 0 ])
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well, yeah, this kind of works, but we still have to write &lt;code&gt;single&lt;&#x2F;code&gt; before each
natural number, can’t we do better? Yes, indeed! using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;agda.readthedocs.io&#x2F;en&#x2F;latest&#x2F;language&#x2F;literal-overloading.html&quot;&gt;literal overloading&lt;&#x2F;a&gt;. If
we define a &lt;code&gt;Number&lt;&#x2F;code&gt; instance for &lt;code&gt;SingleNat&lt;&#x2F;code&gt; then we will be able to write
singleton naturals with plain natural numbers.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;instance
  NumNatSing : ∀ {n} → Number (SingleNat n)
  NumNatSing {n} .Number.Constraint m = n ≡ m
  NumNatSing .Number.fromNat m ⦃ refl ⦄ = single m
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then the example becomes:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;example : BoringList 2
example = 2 ∷ (1 ∷ [ 0 ])
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Perfect! that’s what we needed.&lt;&#x2F;p&gt;
&lt;&#x2F;details&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;With the previous solution in hand, it is easy to imagine how we can
incorporate the same idea into our language.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;proper-references&quot;&gt;Proper references&lt;&#x2F;h3&gt;
&lt;p&gt;Let’s focus on the case of modus ponens (necessitation works analogously).
Assuming the modus ponens instruction entails $ψ$, it should receive one
reference to $ϕ→ψ$ and another reference to $ϕ$. As we mentioned, these
reference will be written as natural numbers by the user, but as we need to
make sure that they are in range and reference the correct formulas, we need
an extra proof object ensuring that. More precisely, assuming we defined the
function &lt;code&gt;lookup-maybe : ∀ {Σ ζ ϕ} → HilbertProof Σ ζ ϕ → Nat → Maybe Fm&lt;&#x2F;code&gt; with the
expected implementation we would require both proof objects
&lt;code&gt;lookup-maybe HP i ≡ just (ϕ ↝ ψ)&lt;&#x2F;code&gt; and &lt;code&gt;lookup-maybe HP j ≡ just ϕ&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But in the case that the references are correct, these proof objects will
always be trivially solved by normalization and reflexivity, hence the code
would look like this:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[ 3 ] (ϕ ↝ (ϕ ↝ ϕ)) ↝ ϕ ↝ ϕ           ByMP 0 ⟨ refl ⟩ , 1 ⟨ refl ⟩
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And we really want to avoid to have the explicit proof object as it makes
the syntax unpleasant. Could we use literal overloading for references to
previous formulas as well? Yes!&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;data HilbertRef {Σ ϕ n} (H : HilbertProof Σ ϕ n) (ψ : Fm) : Set where
  ref : (i : Nat) → lookup-may H i ≡ just ψ → HilbertRef H ψ

instance
  NumRef : ∀ {ϕ Σ n} {H : HilbertProof Σ ϕ n} {ψ} → Number (HilbertRef H ψ)
  NumRef {ϕ} {Σ} {n} {H} {ψ} .Number.Constraint i = lookup-may H i ≡ just ψ
  NumRef {ϕ} {Σ} {n} {H} .Number.fromNat i ⦃ x ⦄ = ref i x
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can write:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;[ 3 ] (ϕ ↝ (ϕ ↝ ϕ)) ↝ ϕ ↝ ϕ                 ByMP 0 , 1
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then each proof object is implicitly embedded in the natural literal &lt;code&gt;0, 1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;compilation&quot;&gt;Compilation&lt;&#x2F;h3&gt;
&lt;p&gt;It is hard to highlight a specific part over the others for the compilation
process. Compilation is mostly about fiddling with types and proof objects
to get the desired translation. If you are interested in this part I suggest
you look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;snippets&#x2F;1858322&quot;&gt;code&lt;&#x2F;a&gt; directly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I hope that you enjoyed the reading. Any comments and suggestions are welcome.&lt;&#x2F;p&gt;
&lt;p&gt;I am not an expert Agda programmer, so in case you look at the
full code, take it with a pinch of salt :)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ASCII fractals in Haskell</title>
        <published>2018-02-20T00:00:00+00:00</published>
        <updated>2018-02-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.janmasrovira.org/blog/ascii-fractals/"/>
        <id>https://blog.janmasrovira.org/blog/ascii-fractals/</id>
        
        <content type="html" xml:base="https://blog.janmasrovira.org/blog/ascii-fractals/">&lt;p&gt;Getting hypnotized by the shape of a fractal is certainly fascinating. In this
blog, we will write a Haskell program that creates fractals from a base pattern.
The recursive nature of the fractals allow a simple implementation in haskell.
In case you don&#x27;t know what a fractal is, I invite you to take a look at the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fractal&quot;&gt;Wikipedia page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So, let&#x27;s start coding. First let&#x27;s write the types for what we want.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;type Pattern = [[Char]]
fractalize :: Pattern -&amp;gt; Int -&amp;gt; Pattern
render :: Pattern -&amp;gt; String
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The function &lt;code&gt;fractalize&lt;&#x2F;code&gt; takes a base pattern and the number of times that we
want to &lt;em&gt;augment&lt;&#x2F;em&gt; it. It returns the resulting fractal.&lt;&#x2F;p&gt;
&lt;p&gt;Given a pattern, let $n, m$ be the number of rows and columns of the base
pattern. We define:&lt;&#x2F;p&gt;
&lt;p&gt;\[
charAt(k, i, k)=
\begin{cases}
p[i][j], &amp;amp; \text{if } k = 1 \\
\text{&#x27; &#x27;}  &amp;amp; \text{if } charAt(k - 1, \frac{i}n, \frac{j}m) = \text{&#x27; &#x27;} \\
p[i\bmod n][j\bmod m], &amp;amp; \text{otherwise}
\end{cases}
\]&lt;&#x2F;p&gt;
&lt;p&gt;This function returns the character in the resulting fractal at the specified
position.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s translate it into haskell code:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;fractalize :: Pattern -&amp;gt; Int -&amp;gt; Pattern
fractalize [] _ = []
fractalize pat k = [ [ charAt k i j | j &amp;lt;- [0..m^k - 1] ] | i &amp;lt;- [0..n^k - 1] ]
  where
    n = length pat
    m = length (head pat)
    charAt k i j
      | k &amp;lt;= 1 = pat!!i!!j
      | &amp;#39; &amp;#39; == charAt (k - 1) (i`div`n) (j`div`m) = &amp;#39; &amp;#39;
      | otherwise = pat!!(i`mod`n)!!(j`mod`m)

render :: Pattern -&amp;gt; String
render = unlines
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s try this base pattern:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;pattern1 :: Pattern
pattern1 = [ &amp;quot; # &amp;quot;
           , &amp;quot;###&amp;quot;
           , &amp;quot; # &amp;quot;]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fractalizing the pattern three times gives:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;             #
            ###
             #
          #  #  #
         #########
          #  #  #
             #
            ###
             #
    #        #        #
   ###      ###      ###
    #        #        #
 #  #  #  #  #  #  #  #  #
###########################
 #  #  #  #  #  #  #  #  #
    #        #        #
   ###      ###      ###
    #        #        #
             #
            ###
             #
          #  #  #
         #########
          #  #  #
             #
            ###
             #
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Cool! let&#x27;s try another pattern!&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;pattern2 :: Pattern
pattern2 = [ &amp;quot;# #&amp;quot;
           , &amp;quot; # &amp;quot;
           , &amp;quot;# #&amp;quot;]
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Result:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;# #   # #         # #   # #
 #     #           #     #
# #   # #         # #   # #
   # #               # #
    #                 #
   # #               # #
# #   # #         # #   # #
 #     #           #     #
# #   # #         # #   # #
         # #   # #
          #     #
         # #   # #
            # #
             #
            # #
         # #   # #
          #     #
         # #   # #
# #   # #         # #   # #
 #     #           #     #
# #   # #         # #   # #
   # #               # #
    #                 #
   # #               # #
# #   # #         # #   # #
 #     #           #     #
# #   # #         # #   # #
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Awesome!&lt;&#x2F;p&gt;
&lt;p&gt;The glue code of our main program is very simple. The number of augments is passed
as an argument to the program.&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code data-lang=&quot;haskell&quot;&gt;main :: IO ()
main = getK &amp;gt;&amp;gt;= putStr . render . fractalize pattern1
  where getK = read . head &amp;lt;$&amp;gt; getArgs
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order to run the example by yourself, get the full code from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;snippets&#x2F;1699946&quot;&gt;here&lt;&#x2F;a&gt; and run:&lt;&#x2F;p&gt;
&lt;pre&gt;&lt;code&gt;runhaskell fractals.hs 3
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We are done! Try your base patterns and have fun!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;final-comments&quot;&gt;Final comments&lt;&#x2F;h1&gt;
&lt;p&gt;It could be nice to adapt the code to use arrays with constant access time
instead of lists, but for small inputs it is irrelevant.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
