tag:blogger.com,1999:blog-51318167582847113432024-03-12T21:44:50.727-07:00Agda explorationseffectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-5131816758284711343.post-4821705590025688092016-12-23T02:06:00.001-08:002017-01-07T12:59:27.424-08:00Higher effects<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>HEff.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-field {
/* agda2-highlight-field-face */
color: #ee1289;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-primitive {
/* agda2-highlight-primitive-face */
color: #0000cd;
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-record {
/* agda2-highlight-record-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
.comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">OPTIONS</span> <span class="comment-delimiter">--</span><span class="comment">type-in-type #-}
</span>
<span class="comment-delimiter">-- </span><span class="comment">This post is also available at https://github.com/effectfully/blog/blob/master/HEff.agda
</span><span class="comment-delimiter">-- </span><span class="comment">in the case it renders incorrectly.
</span><span class="comment-delimiter">-- </span><span class="comment">This post is a sequel of the previous post [1]. There we've seen how simple algebraic effects
</span><span class="comment-delimiter">-- </span><span class="comment">can be modeled in a dependently typed language. This time we'll see how Idris-like
</span><span class="comment-delimiter">-- </span><span class="comment">resource-dependent effects [2] can be defined such that the non-termination and
</span><span class="comment-delimiter">-- </span><span class="comment">"Codensity" effects are expressible too. The reader is assumed to be familiar with Idris effects.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">HEff</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Some prelude first.
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">[_]</span></span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Empty</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Unit.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Sum</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span> <span class="agda2-highlight-symbol">as</span> <span class="agda2-highlight-module">Product</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">[_]</span></span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Prelude</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infix</span> <span class="agda2-highlight-number">3</span> _∈_ _∈₁_ _∈²_
<span class="agda2-highlight-keyword">infix</span> <span class="agda2-highlight-number">4</span> [_]_≅_
<span class="agda2-highlight-keyword">instance</span>
<span class="agda2-highlight-function">inj₁-instance</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">inj₁-instance</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">inj₂-instance</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">inj₂-instance</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="comment-delimiter">-- </span><span class="comment">See https://lists.chalmers.se/pipermail/agda/2016/009069.html
</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">[_]_≅_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">x₁</span> <span class="agda2-highlight-bound-variable">x₂</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x₁</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x₂</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">[</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">]</span></span> <span class="agda2-highlight-bound-variable">y₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≅</span></span> <span class="agda2-highlight-bound-variable">y₂</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">_≡_</span></span> <span class="agda2-highlight-symbol">{</span>A <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">y₁</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">y₂</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<×>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><×></span></span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∈_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">⊥</span>
<span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="comment-delimiter">-- </span><span class="comment">`List₁` is defined as a function rather than a data, because this way we get
</span> <span class="comment-delimiter">-- </span><span class="comment">eta-expansion for free. I'm not sure if this is needed in the code below,
</span> <span class="comment-delimiter">-- </span><span class="comment">but it was needed when I was writing a library some time ago.
</span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">head₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">head₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">tail₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">tail₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">ys</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∈₁_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∈₁_</span></span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">⊥</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∈₁_</span></span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">[</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">]</span></span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≅</span></span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈₁</span></span> <span class="agda2-highlight-bound-variable">ys</span>
<span class="agda2-highlight-function">replace₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ys</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈₁</span></span> <span class="agda2-highlight-bound-variable">ys</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">replace₁</span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span>ys <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">()</span>
<span class="agda2-highlight-function">replace₁</span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">{</span>ys <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">ys</span>
<span class="agda2-highlight-function">replace₁</span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">{</span>ys <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">replace₁</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="comment-delimiter">-- </span><span class="comment">`x , y ∈² xs , ys` is a proof that `x` occurs at the same index in `xs` as `y` in `ys`.
</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∈²_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∈²_</span></span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">z₁</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">⊥</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∈²_</span></span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">z₁</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">y₂</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">z₂</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">zs</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">=</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">[</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><×></span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">]</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">z₁</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≅</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y₂</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">z₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">y₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">z₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">ys</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">zs</span>
<span class="agda2-highlight-function">to∈₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ys</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">zs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">ys</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">zs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈₁</span></span> <span class="agda2-highlight-bound-variable">zs</span>
<span class="agda2-highlight-function">to∈₁</span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">()</span>
<span class="agda2-highlight-function">to∈₁</span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">to∈₁</span> <span class="agda2-highlight-symbol">{</span>xs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">to∈₁</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">HList</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">HList</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-function">id</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">Prelude</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">EffectModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">The type of effects in Idris is defined like this:
</span>
<span class="comment-delimiter">-- </span><span class="comment">Effect : Type
</span> <span class="comment-delimiter">-- </span><span class="comment">Effect = (result : Type) ->
</span> <span class="comment-delimiter">-- </span><span class="comment">(input_resource : Type) ->
</span> <span class="comment-delimiter">-- </span><span class="comment">(output_resource : result -> Type) -> Type
</span>
<span class="comment-delimiter">-- </span><span class="comment">We'll use a similar definition. There are two differences:
</span> <span class="comment-delimiter">-- </span><span class="comment">1) Since resources are not necessary types,
</span> <span class="comment-delimiter">-- </span><span class="comment">`Effect` is parametrized by the type of its resources.
</span> <span class="comment-delimiter">-- </span><span class="comment">2) `input_resource` is the first argument, because it's often a parameter of some particular
</span> <span class="comment-delimiter">-- </span><span class="comment">effect and Agda explicitly distinguishes between parameters and indices unlike Idris
</span> <span class="comment-delimiter">-- </span><span class="comment">(and hence it's often convenient to define an effect without an `input_resource`,
</span> <span class="comment-delimiter">-- </span><span class="comment">and bound `input_resource` in parameters telescope instead).
</span>
<span class="comment-delimiter">-- </span><span class="comment">So the definition could be
</span>
<span class="comment-delimiter">-- </span><span class="comment">Effect : Set -> Set
</span> <span class="comment-delimiter">-- </span><span class="comment">Effect R = R -> (A : Set) -> (A -> R) -> Set
</span>
<span class="comment-delimiter">-- </span><span class="comment">where `R` is the type of resources of an effect, but we split the definition due to
</span> <span class="comment-delimiter">-- </span><span class="comment">the parameters-indices distinction mentioned above:
</span>
<span class="comment-delimiter">-- </span><span class="comment">`Effectful` is `Effect` without `input_resource`.
</span> <span class="agda2-highlight-function">Effectful</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Effectful</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Effectful</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-function">ResourcesTypes</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">ResourcesTypes</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">Sets</span>
<span class="comment-delimiter">-- </span><span class="comment">`Ψs : Effects Rs` is a list of effects typed over a list of resources types `Rs`.
</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">ResourcesTypes</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">List₁</span> <span class="agda2-highlight-function">Effect</span>
<span class="comment-delimiter">-- </span><span class="comment">`rs : Resources Rs` is a heterogeneous list of resources of types from `Rs`.
</span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">ResourcesTypes</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">HList</span>
<span class="comment-delimiter">-- </span><span class="comment">A higher effect is an effect that is defined over a list of simple effects and
</span> <span class="comment-delimiter">-- </span><span class="comment">transforms resources of those effects. This notion will be motivated later.
</span> <span class="agda2-highlight-function">HigherEffect</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">HigherEffect</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">HigherEffects</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">HigherEffects</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-function">HigherEffect</span>
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">HApply</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffect</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">constructor</span> <span class="agda2-highlight-inductive-constructor">happlied</span>
<span class="agda2-highlight-keyword">field</span> <span class="agda2-highlight-field">getHApplied</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="comment-delimiter">-- </span><span class="comment">At first I defined this as a data type, but Agda doesn't keep track of polarity of indices
</span> <span class="comment-delimiter">-- </span><span class="comment">and thus doesn't see that `Codensity` below is strictly positive when `Unionʰᵉ` is a data.
</span> <span class="comment-delimiter">-- </span><span class="comment">The `HApply` wrapper allows to infer `Φ` from `Unionʰᵉ (Φ ∷ Φs) Ψs Rs A rs′` just like
</span> <span class="comment-delimiter">-- </span><span class="comment">with the data version.
</span> <span class="agda2-highlight-function">Unionʰᵉ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffects</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HigherEffect</span>
<span class="agda2-highlight-function">Unionʰᵉ</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">⊥</span>
<span class="agda2-highlight-function">Unionʰᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">HApply</span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-function">Unionʰᵉ</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="comment-delimiter">-- </span><span class="comment">"Constructors" of `Unionʰᵉ`.
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">hereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">happlied</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">a</span>
<span class="comment-delimiter">-- </span><span class="comment">The union of simple effects is a higher effect.
</span> <span class="comment-delimiter">-- </span><span class="comment">This is a direct counterpart of `Unionᵉ` defined in the previous post.
</span> <span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Unionᵉ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffect</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Injecting an effect into some union of effects
</span> <span class="comment-delimiter">-- </span><span class="comment">changes the resource at the position where the effect occurs (1).
</span> <span class="agda2-highlight-inductive-constructor">hereᵉ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Unionᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">Injecting an effect into some union of effects
</span> <span class="comment-delimiter">-- </span><span class="comment">doesn't change the resources of all other effects.
</span> <span class="agda2-highlight-inductive-constructor">thereᵉ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Unionᵉ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Unionᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">hinj</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Unionʰᵉ</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-function">hinj</span> <span class="agda2-highlight-symbol">{</span>Φs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">()</span>
<span class="agda2-highlight-function">hinj</span> <span class="agda2-highlight-symbol">{</span>Φs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">hereʰᵉ</span>
<span class="agda2-highlight-function">hinj</span> <span class="agda2-highlight-symbol">{</span>Φs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">hinj</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="comment-delimiter">-- </span><span class="comment">This is another way to express (1).
</span> <span class="agda2-highlight-function">inj′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Unionᵉ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">replace₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">to∈₁</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">inj′</span> <span class="agda2-highlight-symbol">{</span>Rs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">()</span>
<span class="agda2-highlight-function">inj′</span> <span class="agda2-highlight-symbol">{</span>Rs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">hereᵉ</span>
<span class="agda2-highlight-function">inj′</span> <span class="agda2-highlight-symbol">{</span>Rs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">thereᵉ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">inj′</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="comment-delimiter">-- </span><span class="comment">If an effect doesn't change its resource, then the resources of the union of effects
</span> <span class="comment-delimiter">-- </span><span class="comment">don't change as well.
</span> <span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">r</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Unionᵉ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-symbol">{</span>Rs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">()</span>
<span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-symbol">{</span>Rs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">hereᵉ</span>
<span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-symbol">{</span>Rs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">thereᵉ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">EffectModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">IFreerModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">2</span> _>>=_ _>=>_
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">1</span> _>>_
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">6</span> _<$>_ _<*>_
<span class="comment-delimiter">-- </span><span class="comment">`IFreer` is the indexed counterpart of `Freer` and it's an effect transformer too.
</span> <span class="comment-delimiter">-- </span><span class="comment">`IFreer` is a Hoare state monad (in the sense of [3]; [4] is relevant here too).
</span> <span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′</span>
<span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′′</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′′</span>
<span class="agda2-highlight-function">liftᶠ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span>
<span class="agda2-highlight-function">liftᶠ</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-inductive-constructor">return</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_>>=_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r′′</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r′′</span>
<span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">g</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_>=>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r₃</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r₂</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r₂</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r₃</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r₃</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>=></span></span> <span class="agda2-highlight-bound-variable">g</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">g</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_>>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">r₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r′′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r′′</span>
<span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>></span></span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">c</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<$>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r₂</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">r₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">r₂</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><$></span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">g</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<*>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">r₃</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">r₂</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r₂</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">r₃</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r₁</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">r₃</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><*></span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<$></span></span> <span class="agda2-highlight-bound-variable">b</span>
<span class="agda2-highlight-function">hoistIFreer</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">r′</span>
<span class="agda2-highlight-function">hoistIFreer</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">hoistIFreer</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">hoistIFreer</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">IFreerModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">EffModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Some convenience.
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">hereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span>
<span class="comment-delimiter">-- </span><span class="comment">The main definition. `HEff` describes a computation over a list of simple effects
</span> <span class="comment-delimiter">-- </span><span class="comment">and a list of higher effects that contains the `Unionᵉ` higher effect.
</span> <span class="comment-delimiter">-- </span><span class="comment">The idea is that besides performing some local effectful calls like getting
</span> <span class="comment-delimiter">-- </span><span class="comment">the state in a stateful computation, we can also perform some "big" effectful calls that
</span> <span class="comment-delimiter">-- </span><span class="comment">can change resources of several simple effects. This is why `Unionᵉ` is a higher effect --
</span> <span class="comment-delimiter">-- </span><span class="comment">it's aware of resources of simple effects and changes the row of resources
</span> <span class="comment-delimiter">-- </span><span class="comment">(by transforming one particular resource) when a simple effectful call is performed.
</span> <span class="comment-delimiter">-- </span><span class="comment">Unlike `Eff` in Idris `HEff` doesn't allow to change effects -- only their resources.
</span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffects</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HigherEffect</span>
<span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">IFreer</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Unionʰᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Unionᵉ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">hinvoke</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-function">hinvoke</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">liftᶠ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">hinj</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-function">invoke′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">replace₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">to∈₁</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">invoke′</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">liftᶠ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">hereʰᵉ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">inj′</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">r</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">liftᶠ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">hereʰᵉ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="comment-delimiter">-- </span><span class="comment">An equivalent of `execEff` from the previous post, only for higher effects.
</span> <span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffect</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">hereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">hshift</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffect</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Φ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-function">hshift</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">hoistIFreer</span> <span class="agda2-highlight-symbol">λ</span>
<span class="agda2-highlight-symbol">{</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">hereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">hereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span>
<span class="agda2-highlight-symbol">;</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">}</span>
<span class="comment-delimiter">-- </span><span class="comment">`Eff` describes a computation with no higher effects except for `Unionᵉ`.
</span> <span class="comment-delimiter">-- </span><span class="comment">I.e. it's the usual `Eff`.
</span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffect</span>
<span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-symbol">()</span> <span class="agda2-highlight-symbol">_)</span>
<span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-symbol">()</span> <span class="agda2-highlight-symbol">_)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">EffModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">StateModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">The heterogeneous state effect. Its resource is of type `Set`.
</span> <span class="comment-delimiter">-- </span><span class="comment">`Get` doesn't changes the resource. `Put` changes the resource
</span> <span class="comment-delimiter">-- </span><span class="comment">from `S` (the current state) to `T` (the state after `Put` is called).
</span> <span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effectful</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">Get</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">S</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">Put</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">T</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">T</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">T</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">get</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">get</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-inductive-constructor">Get</span>
<span class="agda2-highlight-function">zap</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">T</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">T</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">zap</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">invoke′</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">Put</span>
<span class="agda2-highlight-function">put</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">put</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">Put</span>
<span class="agda2-highlight-function">modify′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">T</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">T</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">modify′</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">get</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function">zap</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">f</span>
<span class="agda2-highlight-function">modify</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">S</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">modify</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">get</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function">put</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">f</span>
<span class="comment-delimiter">-- </span><span class="comment">`rs′` returns a final resource of `State` and final resources of other effects, hence
</span> <span class="comment-delimiter">-- </span><span class="comment">when the `State` effect is handled resulting computation returns a value of the same type
</span> <span class="comment-delimiter">-- </span><span class="comment">as the original computations returns plus a final resource of `State`.
</span> <span class="comment-delimiter">-- </span><span class="comment">I.e. this is like the usual `S -> B × S`, but, since the state is heterogeneous and
</span> <span class="comment-delimiter">-- </span><span class="comment">can depend on the value returned, it's more like `S -> Σ B T`.
</span> <span class="comment-delimiter">-- </span><span class="comment">Resources of all other effects remain untouched.
</span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">S</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">head₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">tail₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-field">proj₁</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">s</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">hereᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-keyword">with</span> <span class="agda2-highlight-bound-variable">a</span>
<span class="agda2-highlight-symbol">...</span> <span class="agda2-highlight-symbol">|</span> <span class="agda2-highlight-inductive-constructor">Get</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">s</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">...</span> <span class="agda2-highlight-symbol">|</span> <span class="agda2-highlight-inductive-constructor">Put</span> <span class="agda2-highlight-bound-variable">s'</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s'</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">thereᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-symbol">()</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">StateModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">ErrorModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">The error effect is almost the same as before, since its resource is trivial.
</span> <span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">Throw</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-datatype">⊥</span> <span class="agda2-highlight-symbol">_</span>
<span class="comment-delimiter">-- </span><span class="comment">Note that `throw` transforms initial resources into whatever other resources.
</span> <span class="comment-delimiter">-- </span><span class="comment">Indeed, we need to be able to throws errors via the `Error` effect in any part of
</span> <span class="comment-delimiter">-- </span><span class="comment">a computation: it's not required that initial and final resources must match --
</span> <span class="comment-delimiter">-- </span><span class="comment">`throw` is not `return`.
</span> <span class="agda2-highlight-function">throw</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-function">throw</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Throw</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function">⊥-elim</span>
<span class="comment-delimiter">-- </span><span class="comment">But this means that if a computation threw an error, it's not known in what state
</span> <span class="comment-delimiter">-- </span><span class="comment">resources were. I.e. resources became existential. Therefore in order to handle `Error`,
</span> <span class="comment-delimiter">-- </span><span class="comment">we must "deexistentialize" resources. Hence `execError` returns a computation that
</span> <span class="comment-delimiter">-- </span><span class="comment">returns `E ⊎ B` like before, but also attaches `Resources Rs` to `E`. I.e. if a computation
</span> <span class="comment-delimiter">-- </span><span class="comment">threw an error, then return also resources so we can make them final via `[ proj₂ , _ ]`
</span> <span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">[</span></span> <span class="agda2-highlight-field">proj₂</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">tail₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">]′</span></span>
<span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">hereᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Throw</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_))</span>
<span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">thereᵉ</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-symbol">()</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">But having exisentials means there is some CPS lying around.
</span> <span class="comment-delimiter">-- </span><span class="comment">Instead of returning resources on failing we can just handle errors such that
</span> <span class="comment-delimiter">-- </span><span class="comment">no matter what resources are, they are always transformed to what is required.
</span> <span class="agda2-highlight-function">catchError</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">tail₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">tail₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">catchError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">catchError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">hereᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Throw</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">catchError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">thereᵉ</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">catchError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">h</span>
<span class="agda2-highlight-function">catchError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-symbol">()</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">h</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">ErrorModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">StateTest</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Fin</span>
<span class="comment-delimiter">-- </span><span class="comment">Here's an example.
</span>
<span class="comment-delimiter">-- </span><span class="comment">final resources producer ----------------------------|
</span> <span class="comment-delimiter">-- </span><span class="comment">result is of type ----------------------------| |
</span> <span class="comment-delimiter">-- </span><span class="comment">initial resources ------------------| | |
</span> <span class="comment-delimiter">-- </span><span class="comment">effects ----------| | | |
</span> <span class="comment">fpred : Eff (Error ⊤ , State , tt) (tt , ℕ , tt) ℕ (λ n -> tt , Fin n , tt)</span>
<span class="agda2-highlight-function">fpred</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">get</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-symbol">λ</span>
<span class="agda2-highlight-symbol">{</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">throw</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-symbol">;</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">zap</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">fromℕ</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>></span></span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">}</span>
<span class="comment-delimiter">-- </span><span class="comment">`fpred` gets the current state, if it's `0`, then it throws an error,
</span> <span class="comment-delimiter">-- </span><span class="comment">if it's `suc n`, then puts `fromℕ n` in the state and returns `suc n`.
</span> <span class="comment-delimiter">-- </span><span class="comment">Note that the type signature of `fpred` guarantees that the value in a final state
</span> <span class="comment-delimiter">-- </span><span class="comment">is always of type `Fin n` where `n` is what the computation returned.
</span> <span class="comment-delimiter">-- </span><span class="comment">And indeed `fromℕ n` has type `Fin (suc n)`.
</span> <span class="comment-delimiter">-- </span><span class="comment">If we try to return `n` instead of `suc n` we'll get the following very useful error:
</span>
<span class="comment-delimiter">-- </span><span class="comment">No instance of type
</span> <span class="comment-delimiter">-- </span><span class="comment">((Set , State , ℕ) ≡ (⊤ , Error ⊤ , tt) ⊎
</span> <span class="comment-delimiter">-- </span><span class="comment">(Set , State , ℕ) ≡ (Set , State , ℕ) ⊎ ⊥)
</span> <span class="comment-delimiter">-- </span><span class="comment">was found in scope.
</span>
<span class="comment-delimiter">-- </span><span class="comment">But if we explicitly fill the instance argument to `zap` the error becomes
</span>
<span class="comment-delimiter">-- </span><span class="comment">suc x != x of type ℕ
</span>
<span class="comment-delimiter">-- </span><span class="comment">A more general type signature for `fpred`:
</span>
<span class="comment-delimiter">-- </span><span class="comment">fpred : ∀ {Rs rs} {Ψs : Effects Rs}
</span> <span class="comment-delimiter">-- </span><span class="comment">{{err : Error ⊤ , tt ∈² Ψs , rs}} {{st : State , ℕ ∈² Ψs , rs}}
</span> <span class="comment-delimiter">-- </span><span class="comment">-> Eff Ψs rs ℕ (λ n -> replace₁ (Fin n) (to∈₁ st))
</span>
<span class="comment-delimiter">-- </span><span class="comment">(Having to deal with `replace₁` is slightly annoying. Since resources are independent
</span> <span class="comment-delimiter">-- </span><span class="comment">on each other, we perhaps can do better).
</span>
<span class="comment-delimiter">-- </span><span class="comment">A couple of tests:
</span>
<span class="comment-delimiter">-- </span><span class="comment">state ----------------------------------------------------------------|
</span> <span class="comment-delimiter">-- </span><span class="comment">resources ----------------------------------------------------| |
</span> <span class="comment-delimiter">-- </span><span class="comment">error -------------------------------------------------| | |
</span> <span class="agda2-highlight-function">test₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">$</span></span> <span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-function">fpred</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">test₀</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">state ----------------------------------------------------|
</span> <span class="comment-delimiter">-- </span><span class="comment">result -----------------------------------------------| |
</span> <span class="agda2-highlight-function">test₂</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-number">2</span> $ <span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-function">fpred</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-number">2</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">Fin.suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">test₂</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">GeneralModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Now general recursion stuff. Imagine a function that receives a value and returns some other
</span> <span class="comment-delimiter">-- </span><span class="comment">value, but also performs various effectful calls and changes resources of effects.
</span> <span class="comment-delimiter">-- </span><span class="comment">A delayed recursive call must change resources as well, because that's what an actual
</span> <span class="comment-delimiter">-- </span><span class="comment">recursive call does. And hence we have a higher effect that transforms resources
</span> <span class="comment-delimiter">-- </span><span class="comment">of simple effects.
</span>
<span class="comment-delimiter">-- </span><span class="comment">`General` is a true inductive family. See `rs′′` appears twice? The first one is what
</span> <span class="comment-delimiter">-- </span><span class="comment">you pass to the effect and the second one is what a whole computation returns.
</span> <span class="comment-delimiter">-- </span><span class="comment">I.e. a computation that has the `General A rs′ B rs′′` effect always returns `rs′′` as
</span> <span class="comment-delimiter">-- </span><span class="comment">a final resources producer. If it pretends to return something else, then this something else
</span> <span class="comment-delimiter">-- </span><span class="comment">unifies with `rs′′` once pattern matching on `Rec` is performed. This is just like with
</span> <span class="comment-delimiter">-- </span><span class="comment">`x ≡ y`: you can write distinct `x` and `y` there, but once you pattern matched on `refl`,
</span> <span class="comment-delimiter">-- </span><span class="comment">they're unified. Two appearances of `rs′` are treated similarly.
</span> <span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffect</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">Rec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′′</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="comment-delimiter">-- </span><span class="comment">The `λ {_} → ...` part is due to the notorious hidden-lambda bug (see [7]).
</span> <span class="agda2-highlight-function">rec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs′′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">_</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">→</span> <span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-function">rec</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">hinvoke</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">Rec</span>
<span class="comment-delimiter">-- </span><span class="comment">A function of type `Π A Φs Ψs (λ x -> rs′ x , B x , rs′′)` is a function
</span> <span class="comment-delimiter">-- </span><span class="comment">that receives a value of type `A`, can perform higher effects from `Φs` and
</span> <span class="comment-delimiter">-- </span><span class="comment">simple effects from Ψs. Its initial resources of effects are `rs′ x` for the `x` received,
</span> <span class="comment-delimiter">-- </span><span class="comment">it returns `B x` (for the same `x`) and the final resources producer is `rs′′`.
</span> <span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HigherEffects</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-keyword">let</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-keyword">in</span>
<span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">F</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-field">proj₂</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">F</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₂</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">$</span></span> <span class="agda2-highlight-field">proj₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">_))</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="comment-delimiter">-- </span><span class="comment">At the value level the next three functions are just the same as their non-dependent
</span> <span class="comment-delimiter">-- </span><span class="comment">counterparts from the previous post.
</span> <span class="agda2-highlight-function">execGeneral</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs′′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′′</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-function">execGeneral</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">hexecEff</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-function">h</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">This is where the aforementioned unification plays its role.
</span> <span class="comment-delimiter">-- </span><span class="comment">Pattern matching on `Rec` reveals that universally quantified `rs` is actually `rs′ x`
</span> <span class="comment-delimiter">-- </span><span class="comment">and the final resources producers are unified too.
</span> <span class="agda2-highlight-function">h</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">Bx</span> <span class="agda2-highlight-bound-variable">rs′′′</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′′</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">Bx</span> <span class="agda2-highlight-bound-variable">rs′′′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">Bx</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′′′</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-function">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Rec</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">k</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NON_TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-function">execApply</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">F</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">execApply</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execGeneral</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">execApply</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">F</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈²</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-field">proj₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">throw</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execGeneral</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">GeneralModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">TestGeneral</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Fin</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">_+_</span></span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Vec</span> <span class="agda2-highlight-symbol">as</span> <span class="agda2-highlight-module">Vec</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">_>>=_</span></span><span class="agda2-highlight-symbol">;</span> <span class="agda2-highlight-function">sum</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is a contrived example.
</span> <span class="comment-delimiter">-- </span><span class="comment">The type level reads as follows: `ones` receives a number and returns an effectful
</span> <span class="comment-delimiter">-- </span><span class="comment">computation that has the `State` and `General` effects; initially, a `Fin (suc n)` is
</span> <span class="comment-delimiter">-- </span><span class="comment">in the state; the computation returns a list of numbers `xs` and puts
</span> <span class="comment-delimiter">-- </span><span class="comment">a `Vec ℕ n × Fin (suc (sum xs))` into the state.
</span> <span class="comment-delimiter">-- </span><span class="comment">At the value level `ones` performs delayed recursive calls until the `Fin` in the state is
</span> <span class="comment-delimiter">-- </span><span class="comment">`zero`. An argument to delayed recursive calls grows at each call (from `n` to `suc n`).
</span> <span class="comment-delimiter">-- </span><span class="comment">When a `Fin` becomes `zero`, we put a vector of `0`s and `zero` into the state.
</span> <span class="comment-delimiter">-- </span><span class="comment">But since `n` was grown, the length of the vector is greater than original `n` and
</span> <span class="comment-delimiter">-- </span><span class="comment">hence after each delayed recursive call we truncate the vector (and also grow a `Fin`):
</span> <span class="comment-delimiter">-- </span><span class="comment">the `modify′ {{p}} (Product.map Vec.tail suc)` part. In order to be able to grow a `Fin`,
</span> <span class="comment-delimiter">-- </span><span class="comment">we must prepend `1` to the resulting list, because `suc` transforms a `Fin n` into a
</span> <span class="comment-delimiter">-- </span><span class="comment">`Fin (suc n)` and we can't violate the guarantees provided by type signature.
</span> <span class="comment-delimiter">-- </span><span class="comment">So `ones` truncates the `Fin` in the state before each recursive call, performs the call
</span> <span class="comment-delimiter">-- </span><span class="comment">and grows the `Fin` back, thus the `Fin` in a final state is always the same as in an initial.
</span> <span class="agda2-highlight-function">ones</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Resources</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">sum</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)))</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span>
<span class="agda2-highlight-function">ones</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">get</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-inductive-constructor">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-symbol">λ</span>
<span class="agda2-highlight-symbol">{</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">zap</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-inductive-constructor">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Vec.replicate</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>></span></span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-symbol">;</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">zap</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-inductive-constructor">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">inject₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">inject₁</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>></span></span>
<span class="agda2-highlight-function">rec</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-inductive-constructor">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span>
<span class="agda2-highlight-function">modify′</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-inductive-constructor">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Product.map</span> <span class="agda2-highlight-function">Vec.tail</span> <span class="agda2-highlight-inductive-constructor">suc</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>></span></span>
<span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-keyword">where</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">p</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">`p` is a number of steps to perform, `i` is an initial `Fin` in the state.
</span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-number">4</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">sum</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">run</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">$</span></span> <span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-function">ones</span> <span class="agda2-highlight-number">3</span>
<span class="agda2-highlight-function">test₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">test₀</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">test₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-number">2</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">test₁</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">test₂</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-number">3</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">+</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">test₂</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">test₃</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)))</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">test₃</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">CodensityModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">2</span> _⟨>>=⟩_ _⟨>>=⟩′_
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">1</span> _⟨>>⟩_
<span class="comment-delimiter">-- </span><span class="comment">Let's see another example of a higher effect.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Free monads and their relatives are known to be inefficient wrt left-nested binds.
</span> <span class="comment-delimiter">-- </span><span class="comment">The situation is similar to that of lists: left-nested appends result in quadratic performance,
</span> <span class="comment-delimiter">-- </span><span class="comment">while right-nested appends have linear performance. A common way to mitigate the situation
</span> <span class="comment-delimiter">-- </span><span class="comment">is to use difference lists: they have O(1) append and it takes O(n) time to reify a difference
</span> <span class="comment-delimiter">-- </span><span class="comment">list into an actual one. The same trick can be used to improve performance of free monads and
</span> <span class="comment-delimiter">-- </span><span class="comment">that's what [5] does.
</span> <span class="comment-delimiter">-- </span><span class="comment">[6] takes a different perspective: instead of performing binds the authors chose to collect
</span> <span class="comment-delimiter">-- </span><span class="comment">them in a data type which gives same O(1) `bind`. Their approach is much smarter than what
</span> <span class="comment-delimiter">-- </span><span class="comment">I'm going to show and I believe it should be adopted in a practical library (there would be
</span> <span class="comment-delimiter">-- </span><span class="comment">termination checking issues, but they probably can be solved with sized types), but
</span> <span class="comment-delimiter">-- </span><span class="comment">nevertheless this example is nice.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is the effect. Looks quite intimidating, right? But the idea is simple: we package
</span> <span class="comment-delimiter">-- </span><span class="comment">an effectful computation (which has this same `Codensity` effect too) with a bind continuation
</span> <span class="comment-delimiter">-- </span><span class="comment">instead of actually performing `_>>=_`.
</span> <span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HigherEffect</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">Bind</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="comment-delimiter">-- </span><span class="comment">And this is what we get on invoking `Bind`. The idea is that left-nested calls to `_⟨>>=⟩_`
</span> <span class="comment-delimiter">-- </span><span class="comment">stack via the `Codensity` effect instead of being computed like with `_>>=_`.
</span> <span class="comment-delimiter">-- </span><span class="comment">Right-nested calls are disallowed so far, since the bind continuation doesn't have the
</span> <span class="comment-delimiter">-- </span><span class="comment">`Codensity` effect.
</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⟨>>=⟩_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟨>>=⟩</span></span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">hinvoke</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Bind</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-bound-variable">g</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⟨>>⟩_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs₂</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs₁</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟨>>⟩</span></span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟨>>=⟩</span></span> <span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">c</span>
<span class="comment-delimiter">-- </span><span class="comment">Here we reassociate binds via CPS by growing the `k₃` continuation.
</span> <span class="comment-delimiter">-- </span><span class="comment">Just like with difference lists.
</span> <span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k₃</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">k₃</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-bound-variable">k₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k₃</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">simple</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k₂</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k₃</span>
<span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">hereʰᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Bind</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-bound-variable">k₁</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">k₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k₃</span> <span class="agda2-highlight-symbol">=</span>
<span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>=></span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k₂</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k₃</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">thereʰᵉ</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k₃</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">higher</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k₂</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k₃</span>
<span class="agda2-highlight-function">execCodensity</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-function">execCodensity</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">bindCodensity</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-inductive-constructor">return</span>
<span class="comment-delimiter">-- </span><span class="comment">We can also have right-nested computations with the `Codensity` effect.
</span> <span class="comment-delimiter">-- </span><span class="comment">I don't know if we lose much by handling `Codenisty` so early or not, though.
</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⟨>>=⟩′_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">rs′</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">rs′</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">rs′′</span>
<span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟨>>=⟩′</span></span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟨>>=⟩</span></span> <span class="agda2-highlight-function">execCodensity</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">g</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">CodensityModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">TestCodensity</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">This is `replicateM` that generates left-nested `_>>_`s.
</span> <span class="agda2-highlight-function">replicateLeftM</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">replicateLeftM</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function">eₜₜ</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">eₜₜ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><$></span></span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">a</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>></span></span> <span class="agda2-highlight-function">eₜₜ</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">This is `replicateM` that generates left-nested `_⟨>>⟩_`s.
</span> <span class="agda2-highlight-function">replicateCoLeftM</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Rs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">replicateCoLeftM</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">hshift</span> <span class="agda2-highlight-function">eₜₜ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">eₜₜ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><$></span></span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Codensity</span> <span class="agda2-highlight-bound-variable">Φs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Φs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">a</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟨>>⟩</span></span> <span class="agda2-highlight-function">eₜₜ</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">Uncomment this and memory consumption will grow from 117 MB to 880 MB.
</span> <span class="comment-delimiter">-- </span><span class="comment">test₁ : (proj₂ ∘ runEff ∘ execState 0 ∘ replicateLeftM 80 $ modify suc) ≡ 80
</span> <span class="comment-delimiter">-- </span><span class="comment">test₁ = refl
</span>
<span class="comment-delimiter">-- </span><span class="comment">Uncomment this and memory consumption will grow from 117 MB to 160 MB.
</span> <span class="comment-delimiter">-- </span><span class="comment">This version type checks much faster as expected.
</span> <span class="comment-delimiter">-- </span><span class="comment">test₂ : (proj₂ ∘ runEff ∘ execState 0 ∘ execCodensity ∘ replicateCoLeftM 80 $ modify suc) ≡ 80
</span> <span class="comment-delimiter">-- </span><span class="comment">test₂ = refl
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">References</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">[1] "Turing-completeness totally freer"
</span> <span class="comment-delimiter">-- </span><span class="comment">http://effectfully.blogspot.com/2016/12/turing-completeness-totally-freer.html
</span>
<span class="comment-delimiter">-- </span><span class="comment">[2] "The Effects Tutorial"
</span> <span class="comment-delimiter">-- </span><span class="comment">http://docs.idris-lang.org/en/latest/effects/
</span>
<span class="comment-delimiter">-- </span><span class="comment">[3] "Inferring Precise Polymorphic Specifications for the Hoare State Monad",
</span> <span class="comment-delimiter">-- </span><span class="comment">Cole Schlesinger and Nikhil Swamy
</span> <span class="comment-delimiter">-- </span><span class="comment">http://research.microsoft.com/en-us/um/people/nswamy/paper.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[4] "The Hoare State Monad", Wouter Swierstra
</span> <span class="comment-delimiter">-- </span><span class="comment">http://www.staff.science.uu.nl/~swier004/talks/2009-eindhoven.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[5] "Asymptotic Improvement of Computations over Free Monads"
</span> <span class="comment-delimiter">-- </span><span class="comment">http://www.janis-voigtlaender.eu/papers/AsymptoticImprovementOfComputationsOverFreeMonads.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[6] "Freer Monads, More Extensible Effects", Oleg Kiselyov, Hiromi Ishii
</span> <span class="comment-delimiter">-- </span><span class="comment">http://okmij.org/ftp/Haskell/extensible/more.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[7] "Eliminating the problems of hidden-lambda insertion", Marcus Johansson, Jesper Lloyd
</span> <span class="comment-delimiter">-- </span><span class="comment">http://www2.tcs.ifi.lmu.de/~abel/MScThesisJohanssonLloyd.pdf
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0tag:blogger.com,1999:blog-5131816758284711343.post-68469870493710738802016-12-17T03:55:00.002-08:002016-12-17T03:55:34.506-08:00Turing-completeness totally freer<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>Freer.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-record {
/* agda2-highlight-record-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
.comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">OPTIONS</span> <span class="comment-delimiter">--</span><span class="comment">type-in-type #-}
</span>
<span class="comment-delimiter">-- </span><span class="comment">The title (except for the last letter) is shamelessly stolen from [1].
</span><span class="comment-delimiter">-- </span><span class="comment">Here we consider how simple (as opposed to resource-dependent like in Idris) algebraic effects
</span><span class="comment-delimiter">-- </span><span class="comment">can be handled in a dependently typed language and
</span><span class="comment-delimiter">-- </span><span class="comment">how non-termination can be modeled as such an effect.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Freer</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Some boring stuff.
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Empty</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Unit.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Maybe.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Sum</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Prelude</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infix</span> <span class="agda2-highlight-number">4</span> _∈_
<span class="agda2-highlight-keyword">instance</span>
<span class="agda2-highlight-function">inj₁-instance</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">inj₁-instance</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">inj₂-instance</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">inj₂-instance</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="comment-delimiter">-- </span><span class="comment">`_∈_` is defined as a function rather than a data type, because to my experience
</span> <span class="comment-delimiter">-- </span><span class="comment">instance search plays better with functions.
</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∈_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">⊥</span>
<span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">Prelude</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">EffectModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Simple effects are just functors:
</span>
<span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-function">Effect</span>
<span class="comment-delimiter">-- </span><span class="comment">We define the union of effects using explicit recursion instead of `foldr`,
</span> <span class="comment-delimiter">-- </span><span class="comment">because this way Agda sees that `Unionᵉ` is constructor-headed and thus can infer
</span> <span class="comment-delimiter">-- </span><span class="comment">`Ψs` if `Unionᵉ Ψs` is provided.
</span> <span class="agda2-highlight-function">Unionᵉ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Effect</span>
<span class="agda2-highlight-function">Unionᵉ</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">⊥</span>
<span class="agda2-highlight-function">Unionᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-function">Unionᵉ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Unionᵉ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-symbol">{</span>Ψs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">()</span>
<span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-symbol">{</span>Ψs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₁</span>
<span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-symbol">{</span>Ψs <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">EffectModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">FreerModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">2</span> _>>=_
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">1</span> _>>_
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">6</span> _<$>_ _<*>_
<span class="comment-delimiter">-- </span><span class="comment">McBride uses free monads over containers in his paper,
</span> <span class="comment-delimiter">-- </span><span class="comment">but we'll be using Freer monads from [2], because I find them simpler, nicer and they
</span> <span class="comment-delimiter">-- </span><span class="comment">can be extended to dependent effects in a very natural way.
</span>
<span class="comment-delimiter">-- </span><span class="comment">`call` receives a `Ψ A`, which can be seen as a command (or a request),
</span> <span class="comment-delimiter">-- </span><span class="comment">and a continuation which expects a response in `A` and returns an effectful computation.
</span> <span class="comment-delimiter">-- </span><span class="comment">We'll see examples later.
</span> <span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span>
<span class="comment-delimiter">-- </span><span class="comment">Note that `∀ {A} -> Ψ A -> (A -> Freer Ψ B)` is isomorphic to `Ψ (Freer Ψ B)`,
</span> <span class="comment-delimiter">-- </span><span class="comment">which is what can be found in the classical definition of `Free`.
</span> <span class="comment-delimiter">-- </span><span class="comment">However `Ψ (Freer Ψ B)` is not strictly positive, so it can't be used in type theory.
</span> <span class="comment-delimiter">-- </span><span class="comment">`Free F` is also a monad only if `F` is a functor, while `Freer Ψ` is always a monad.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Free monads toolkit:
</span>
<span class="agda2-highlight-function">liftᶠ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">liftᶠ</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-inductive-constructor">return</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_>>=_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">g</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_>>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>></span></span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">c</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<$>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><$></span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">g</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<*>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><*></span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<$></span></span> <span class="agda2-highlight-bound-variable">b</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">FreerModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">EffModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">An effectful computation is just a Freer monad over the union of a list of effects.
</span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Effect</span>
<span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">Freer</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">Unionᵉ</span>
<span class="comment-delimiter">-- </span><span class="comment">If there are no effects in an effectful computation, we can simply return its result.
</span> <span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">()</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">This function invokes a single effect.
</span> <span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">liftᶠ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">inj</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="comment-delimiter">-- </span><span class="comment">This function allows to handle the outermost effect.
</span> <span class="agda2-highlight-function">execEff</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Ψ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">execEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">execEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">execEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">execEff</span> <span class="agda2-highlight-bound-variable">eta</span> <span class="agda2-highlight-bound-variable">phi</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">EffModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">StateModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Our first example is `State`.
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">If the request is `Get`, then a response is in `S`, i.e. the current state.
</span> <span class="agda2-highlight-inductive-constructor">Get</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-bound-variable">S</span>
<span class="comment-delimiter">-- </span><span class="comment">If the request is `Put s`, then a response is in `⊤`, i.e. the response is dummy.
</span> <span class="agda2-highlight-inductive-constructor">Put</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-record">⊤</span>
<span class="comment-delimiter">-- </span><span class="comment">When handling effects, each response must be satisfied,
</span> <span class="comment-delimiter">-- </span><span class="comment">so in order to handle `Get` a value of type `S` is required,
</span> <span class="comment-delimiter">-- </span><span class="comment">and in order to handle `Put` a value of type `⊤` is required, i.e. `tt`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The `State` toolkit:
</span>
<span class="agda2-highlight-function">get</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">S</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">S</span>
<span class="agda2-highlight-function">get</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-inductive-constructor">Get</span>
<span class="agda2-highlight-function">put</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">S</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">put</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">Put</span>
<span class="agda2-highlight-function">modify</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">S</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">S</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">modify</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">get</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function">put</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">f</span>
<span class="comment-delimiter">-- </span><span class="comment">The `State` handler receives an initial state `s`.
</span> <span class="comment-delimiter">-- </span><span class="comment">On `Get` the state is passed to the continuation and on `Put s'` the state is
</span> <span class="comment-delimiter">-- </span><span class="comment">replaced by `s'` such that all future `Get`s will get `s'` rather than the old `s`
</span> <span class="comment-delimiter">-- </span><span class="comment">(until a new `Put` is encountered). All other effects remain untouched.
</span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-bound-variable">S</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-bound-variable">S</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">s</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">Get</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">s</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Put</span> <span class="agda2-highlight-bound-variable">s'</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s'</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">call</span> <span class="agda2-highlight-bound-variable">a</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-bound-variable">s</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">StateModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">ErrorModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">`Error` is the next effect. It could be defined as
</span>
<span class="comment-delimiter">-- </span><span class="comment">data Error E B : Set where
</span> <span class="comment-delimiter">-- </span><span class="comment">Throw : E -> Error E B
</span>
<span class="comment-delimiter">-- </span><span class="comment">but I prefer this version as it plays better with universe polymorphism
</span> <span class="comment-delimiter">-- </span><span class="comment">(which is disabled in this file):
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">Throw</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-datatype">⊥</span>
<span class="agda2-highlight-function">throw</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">throw</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Throw</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-function">⊥-elim</span>
<span class="agda2-highlight-function">runError</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">E</span>
<span class="agda2-highlight-function">runError</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Throw</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="comment-delimiter">-- </span><span class="comment">`execError` handles `Error E` and returns a computation that
</span> <span class="comment-delimiter">-- </span><span class="comment">returns either an error in `E` or a normal value.
</span> <span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execEff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">inj₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">runError</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">ErrorModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">GeneralModule</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Here comes non-termination.
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Effect</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">Rec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">`rec` is a delayed recursive call. It allows to write `f (suc n) = rec n`
</span> <span class="comment-delimiter">-- </span><span class="comment">instead of `f (suc n) = f n`. This matters when a function is not obviously terminating,
</span> <span class="comment-delimiter">-- </span><span class="comment">so you can write its body by replacing recursive calls with `rec` everywhere (or somewhere)
</span> <span class="comment-delimiter">-- </span><span class="comment">and then handle non-termination using a monad of your choice as [1] describes.
</span>
<span class="agda2-highlight-function">rec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">rec</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">invoke</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">Rec</span>
<span class="comment-delimiter">-- </span><span class="comment">An effectful counterpart of McBride's `Π`.
</span> <span class="comment-delimiter">-- </span><span class="comment">A function of type `f : Π A Ψs B` is a function that receives an `x : A`,
</span> <span class="comment-delimiter">-- </span><span class="comment">can perform effects from `Ψs`, can call `rec x` where `x : A` and
</span> <span class="comment-delimiter">-- </span><span class="comment">receive responses in `B x`, and finally returns a `B x`.
</span> <span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Effects</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">`execGeneral f a` replaces each `rec x` in a computation `a` with `f x`.
</span> <span class="comment-delimiter">-- </span><span class="comment">I.e. each delayed recursive call becomes an actual call (but not recursive yet).
</span> <span class="agda2-highlight-function">execGeneral</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">execGeneral</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execEff</span> <span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-function">h</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">h</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Bx</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">General</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">Bx</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Bx</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Rec</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>>=</span></span> <span class="agda2-highlight-bound-variable">k</span>
<span class="comment-delimiter">-- </span><span class="comment">This is how we can run a generally recursive computation.
</span> <span class="comment-delimiter">-- </span><span class="comment">`execApply f x` just applies `f` to `x` and replaces each successive `rec x` with
</span> <span class="comment-delimiter">-- </span><span class="comment">a call to `execApply f`. Thus the computation stops only when there are no more
</span> <span class="comment-delimiter">-- </span><span class="comment">delayed recursive calls. Since `General` allows to model non-terminating computations,
</span> <span class="comment-delimiter">-- </span><span class="comment">an attempt to run such computation can be NON_TERMINATING, obviously.
</span> <span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NON_TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-function">execApply</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execApply</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execGeneral</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">execApply</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">But we can also define something safe. This is the McBride's petrol-driven semantics.
</span> <span class="comment-delimiter">-- </span><span class="comment">If there is no petrol, throw a dummy error.
</span> <span class="comment-delimiter">-- </span><span class="comment">If there is more petrol, force each delayed recursive call.
</span> <span class="comment-delimiter">-- </span><span class="comment">Note that there are no fancy monad morphisms, we only require a list of effects to contain
</span> <span class="comment-delimiter">-- </span><span class="comment">the `Error` effect.
</span> <span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Error</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Eff</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">throw</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">execGeneral</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">I won't consider more involved semantics of non-termination from [1] here.
</span><span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">GeneralModule</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Test</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">A function that halves a natural number.
</span> <span class="agda2-highlight-function">halve</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">halve</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">halve</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">halve</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function">tryHalve</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Maybe</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">tryHalve</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">@(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">_))</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">just</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">halve</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">tryHalve</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">nothing</span>
<span class="comment-delimiter">-- </span><span class="comment">A generally recursive computation that halves a natural number repeatedly,
</span> <span class="comment-delimiter">-- </span><span class="comment">collects all halves in a list and also stores the number of elements in the list in a state.
</span> <span class="comment-delimiter">-- </span><span class="comment">Emphatically, this computation can't be defined using structural recursion directly
</span> <span class="comment-delimiter">-- </span><span class="comment">(though, you can use fancy tricks (like in [3]) to achieve that).
</span> <span class="agda2-highlight-function">halves</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">State</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Ψs</span><span class="agda2-highlight-symbol">}}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Π</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-bound-variable">Ψs</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">halves</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">modify</span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">>></span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷_</span></span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><$></span></span> <span class="agda2-highlight-function">maybe′</span> <span class="agda2-highlight-function">rec</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">return</span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">tryHalve</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">`run` receives a number of recursive calls to perform and a natural number to repeatedly halve.
</span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⊎</span></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">run</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">runEff</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">execError</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">execState</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">execPetrol</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-function">halves</span>
<span class="comment-delimiter">-- </span><span class="comment">Four step are enough to perform to repeatedly halve `10`.
</span> <span class="agda2-highlight-function">test₄</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-number">4</span> <span class="agda2-highlight-number">10</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-number">10</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">5</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">2</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-number">4</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">test₄</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">But three are not.
</span> <span class="agda2-highlight-function">test₃</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-number">10</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">inj₁</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">test₃</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">Just another test.
</span> <span class="agda2-highlight-function">test₅</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">run</span> <span class="agda2-highlight-number">5</span> <span class="agda2-highlight-number">12</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">inj₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-number">12</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">6</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-number">4</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">test₅</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Conclusion</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">We've seen how simple algebraic effects can be handled in a dependently typed setting
</span> <span class="comment-delimiter">-- </span><span class="comment">and how non-termination can be modeled as such an effect.
</span> <span class="comment-delimiter">-- </span><span class="comment">But we can also model Idris-like resource-dependent effects in a similar way
</span> <span class="comment-delimiter">-- </span><span class="comment">and define a non-termination effect in this setting too.
</span> <span class="comment-delimiter">-- </span><span class="comment">It's much more fun, so this is what I'll probably write about next time.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">References</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">[1] "Turing-Completeness Totally Free", Conor McBride
</span> <span class="comment-delimiter">-- </span><span class="comment">https://personal.cis.strath.ac.uk/conor.mcbride/TotallyFree.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[2] "Freer Monads, More Extensible Effects", Oleg Kiselyov, Hiromi Ishii
</span> <span class="comment-delimiter">-- </span><span class="comment">http://okmij.org/ftp/Haskell/extensible/more.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[3] "Assisting Agda's termination checker"
</span> <span class="comment-delimiter">-- </span><span class="comment">http://stackoverflow.com/questions/19642921/assisting-agdas-termination-checker
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0tag:blogger.com,1999:blog-5131816758284711343.post-7188700726663572402016-10-01T07:14:00.003-07:002016-10-01T07:23:00.880-07:00Insane descriptions<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>Insane.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-field {
/* agda2-highlight-field-face */
color: #ee1289;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-primitive {
/* agda2-highlight-primitive-face */
color: #0000cd;
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-record {
/* agda2-highlight-record-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
.comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">OPTIONS</span> <span class="comment-delimiter">--</span><span class="comment">type-in-type #-} -- This is needed only for the `InductiveInductive` module.
</span>
<span class="comment-delimiter">-- </span><span class="comment">In this post I'll show a technique that allows to describe nearly all Agda data types,
</span><span class="comment-delimiter">-- </span><span class="comment">including non-strictly positive and inductive-inductive ones.
</span><span class="comment-delimiter">-- </span><span class="comment">You'll also see how insanely dependent types can be emulated in Agda.
</span><span class="comment-delimiter">-- </span><span class="comment">The reader is assumed to be familiar with descriptions.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Insane</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">Preliminaries:
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Level</span> <span class="agda2-highlight-keyword">using</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">_⊔_</span></span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Empty</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊔_</span></span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Fin</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Sum</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">map</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">map</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">0</span> _∸>_ _⇒_
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">constructor</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∸>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ι</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">⊔</span></span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">⊔</span></span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">unsubst</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">subst</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-bound-variable">z</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">z</span>
<span class="agda2-highlight-function">unsubst</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">id</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is how we describe a constructor of a data type:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="comment-delimiter">-- </span><span class="comment">You're perhaps wondering where I hide inductive occurrences. They are handled by `π`
</span><span class="comment-delimiter">-- </span><span class="comment">just like non-inductive arguments to constructors. It means that we can't distinguish
</span><span class="comment-delimiter">-- </span><span class="comment">between inductive and non-inductive arguments by means of pattern matching and hence
</span><span class="comment-delimiter">-- </span><span class="comment">can't e.g. define a generic `depth` function. So the encoding is far from being perfect,
</span><span class="comment-delimiter">-- </span><span class="comment">but it does allow to define generic `_≟_`, `show` and similar functions
</span><span class="comment-delimiter">-- </span><span class="comment">(using instance arguments). An example in a similar system can be found in [4].
</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is how we can describe the type of Vec's `_∷_`:
</span>
<span class="comment-delimiter">-- </span><span class="comment">`VCons = π ℕ λ n -> π A λ _ -> π (Vec A n) λ _ -> ret (suc n)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">Interpretation of described constructors goes as follows:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="comment-delimiter">-- </span><span class="comment">Each `π` becomes the meta-level `Π` and the final index that a constructor receives
</span><span class="comment-delimiter">-- </span><span class="comment">is interpreted by some provided `B`.
</span><span class="comment-delimiter">-- </span><span class="comment">So `⟦ VCons ⟧ (Vec A)` returns the actual type of `_∷_` (modulo the implicitness of `n`):
</span>
<span class="comment-delimiter">-- </span><span class="comment">`∀ n -> A -> Vec A n -> Vec A (suc n)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">We also need the usual way to interpret propositional/sigma descriptions ([1]/[2]):
</span>
<span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="comment-delimiter">-- </span><span class="comment">A description of a data type is essentially a list of constructors.
</span><span class="comment-delimiter">-- </span><span class="comment">However we allow types of constructors depend on former constructors.
</span>
<span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set₁</span>
<span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="comment-delimiter">-- </span><span class="comment">This means that when defining the type of Vec's `_∷_` you can mention Vec's `[]`.
</span><span class="comment-delimiter">-- </span><span class="comment">It's useless for simple data types, but we'll need it for inductive-inductive ones.
</span>
<span class="comment-delimiter">-- </span><span class="comment">We're now going to define `lookup` for `Desc`. Since each description of a constructor
</span><span class="comment-delimiter">-- </span><span class="comment">depends on all previous constructors, we need to provide these constructors somehow.
</span><span class="comment-delimiter">-- </span><span class="comment">So here is a function that turns the described type of a constructor into actual constructor:
</span>
<span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_,_</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">It's explained in [3].
</span>
<span class="comment-delimiter">-- </span><span class="comment">`cons` is able to construct a `⟦ C ⟧ B`, but it requires a `Extendᶜ C ∸> B` and since
</span><span class="comment-delimiter">-- </span><span class="comment">`lookup i` traverses `i` constructors, we need to provide a `Extendᶜ C ∸> B` for each of them:
</span>
<span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-symbol">{</span>B <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">))</span>
<span class="comment-delimiter">-- </span><span class="comment">`lookup` is now straightforward:
</span>
<span class="agda2-highlight-function">lookupᵈ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-function">lookupᵈ</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">lookupᵈ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">a</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">lookupᵈ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">a</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is what allows to handle inductive and non-inductive occurrences uniformly:
</span>
<span class="agda2-highlight-function">RecDesc</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set₁</span>
<span class="agda2-highlight-function">RecDesc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="comment-delimiter">-- </span><span class="comment">`μ` is defined over `R : RecDesc I n` instead of `D : Desc I B n`.
</span><span class="comment-delimiter">-- </span><span class="comment">In the type of the constructor of `μ` `B` gets instantiated by `μ R`.
</span><span class="comment-delimiter">-- </span><span class="comment">Thus whenever you use `B` in your description, it eventually becomes
</span><span class="comment-delimiter">-- </span><span class="comment">replaced by an inductive occurrence. Here is a quick example:
</span>
<span class="comment-delimiter">-- </span><span class="comment">Vec : Set -> ℕ -> Set
</span><span class="comment-delimiter">-- </span><span class="comment">Vec A = μ λ B -> ret 0
</span><span class="comment-delimiter">-- </span><span class="comment">, λ _ -> (π ℕ λ n -> π A λ _ -> π (B n) λ _ -> ret (suc n))
</span><span class="comment-delimiter">-- </span><span class="comment">, λ _ -> tt
</span>
<span class="comment-delimiter">-- </span><span class="comment">In `μ` `B` gets instantiated by `Vec A` and thus the type of the second constructor
</span><span class="comment-delimiter">-- </span><span class="comment">is described by essentially `π ℕ λ n -> π A λ _ -> π (Vec A n) λ _ -> ret (suc n)`,
</span><span class="comment-delimiter">-- </span><span class="comment">which we've seen above.
</span>
<span class="comment-delimiter">-- </span><span class="comment">However it's not so simple to define `μ`. Consider its simplified version where
</span><span class="comment-delimiter">-- </span><span class="comment">`μ` is defined over a three-constructors data type:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Mu3</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NO_POSITIVITY_CHECK</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">RecDesc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-number">3</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">lookupᵈ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">RecDesc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-number">3</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">())))</span>
<span class="comment-delimiter">-- </span><span class="comment">`node` receives the number of a constructor, `lookup`s for this constructor and
</span> <span class="comment-delimiter">-- </span><span class="comment">`Extend`s it in the usual way. However `lookupᵈ` also receives a `Nodes i (R (μ R))`,
</span> <span class="comment-delimiter">-- </span><span class="comment">which provides `node`s for all constructors up to the `i`th
</span> <span class="comment-delimiter">-- </span><span class="comment">(which are consumed by `cons`es in order to get actual constructors).
</span>
<span class="comment-delimiter">-- </span><span class="comment">Operationally `nodes` is trivial: it's just Data.Vec.tabulate, but returns a tuple
</span> <span class="comment-delimiter">-- </span><span class="comment">rather than a vector, but note that the type of `node` contains multiple `node`s.
</span> <span class="comment-delimiter">-- </span><span class="comment">This is what very/insanely dependent types are about: the ability to mention at the type level
</span> <span class="comment-delimiter">-- </span><span class="comment">the value being defined. Check this example: [5].
</span>
<span class="comment-delimiter">-- </span><span class="comment">Agda does allow to give to constructors insanely dependent types (though, not directly),
</span> <span class="comment-delimiter">-- </span><span class="comment">but she doesn't allow to give to functions such types. And hence we can't define:
</span>
<span class="comment-delimiter">-- </span><span class="comment">nodes : ∀ {I B n} {D : Desc I B n}
</span><span class="comment-delimiter">-- </span><span class="comment">-> (k : ∀ {j} i -> Extendᶜ (lookupᵈ i D (nodes k i)) j -> B j) -> ∀ i -> Nodes i D
</span><span class="comment-delimiter">-- </span><span class="comment">nodes k zero = tt
</span><span class="comment-delimiter">-- </span><span class="comment">nodes k (suc i) = k zero , nodes (k ∘ suc) i
</span>
<span class="comment-delimiter">-- </span><span class="comment">data μ {I n} (R : RecDesc I n) j : Set where
</span><span class="comment-delimiter">-- </span><span class="comment">node : ∀ i -> Extendᶜ (lookupᵈ i (R (μ R)) (nodes node i)) j -> μ R j
</span>
<span class="comment-delimiter">-- </span><span class="comment">`nodes` receives `k` which type mentions both `nodes` and `k`.
</span><span class="comment-delimiter">-- </span><span class="comment">Note that the type of `k` in `nodes` unifies perfectly with the type of `node`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">I don't know whether it's possible to circumvent the problem in some fair way,
</span><span class="comment-delimiter">-- </span><span class="comment">but we can just cheat:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">_</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality.TrustMe</span>
<span class="agda2-highlight-function">renodes</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">nodes</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">lookupᵈ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">nodes</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">D</span>
<span class="agda2-highlight-function">renodes</span> <span class="agda2-highlight-bound-variable">nodes</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">renodes</span> <span class="agda2-highlight-symbol">{</span>D <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">nodes</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span>
<span class="agda2-highlight-function">renodes</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">subst</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₁</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-symbol">_)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₂</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₁</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)))</span>
<span class="agda2-highlight-function">trustMe</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">nodes</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))))</span>
<span class="agda2-highlight-symbol">((λ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">$</span></span>
<span class="agda2-highlight-function">unsubst</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-symbol">_)</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">lookupᵈ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₂</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">_)</span>
<span class="agda2-highlight-function">trustMe</span>
<span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-bound-variable">i</span>
<span class="comment-delimiter">-- </span><span class="comment">`renodes` has the same computational content as `nodes`, but it assumes that `nodes`
</span> <span class="comment-delimiter">-- </span><span class="comment">is already defined (because we need to use it at the type level) and
</span> <span class="comment-delimiter">-- </span><span class="comment">essentially "redefines" it (because we need to compute something eventually).
</span> <span class="comment-delimiter">-- </span><span class="comment">The ability to compute at the type level for `nodes` is given by
</span> <span class="comment-delimiter">-- </span><span class="comment">`trustMe`, `subst` and `unsubst`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">And here is where we actually tie the knot:
</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NO_POSITIVITY_CHECK</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">RecDesc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extendᶜ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">lookupᵈ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">RecDesc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Nodes</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="comment-delimiter">-- </span><span class="comment">This is in order to prevent infinite unfolding of `nodes`.
</span> <span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">renodes</span> <span class="agda2-highlight-function">nodes</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="comment-delimiter">-- </span><span class="comment">Some shortcuts:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⇒_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Cons</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">RecDesc′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set₁</span>
<span class="agda2-highlight-function">RecDesc′</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Desc</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">const</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">μ′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">RecDesc′</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">μ′</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">#₀</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">#₁</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">#₂</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">#₃</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)))</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">#₄</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">))))</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₁</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">())</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₂</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">()))</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₃</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">())))</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₄</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">()))))</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₅</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">())))))</span> <span class="agda2-highlight-symbol">_</span>
<span class="comment-delimiter">-- </span><span class="comment">It's not needed to explicitly refute last clauses using `⟨⟩ᵢ`,
</span><span class="comment-delimiter">-- </span><span class="comment">when `Fin` is defined computationally like this:
</span>
<span class="comment-delimiter">-- </span><span class="comment">Fin : ℕ -> Set
</span><span class="comment-delimiter">-- </span><span class="comment">Fin 0 = ⊥
</span><span class="comment-delimiter">-- </span><span class="comment">Fin 1 = ⊤
</span><span class="comment-delimiter">-- </span><span class="comment">Fin (suc n) = Maybe (Fin n)
</span>
<span class="comment-delimiter">-- </span><span class="comment">but it's a bit inconvenient to use such `Fin`s.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The described dependently typed hello-world:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Simple</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Vec′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Vec′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">Vec′A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">Vec′A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">[]′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₀</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷′_</span></span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Vec→Vec′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">Vec→Vec′</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]′</span>
<span class="agda2-highlight-function">Vec→Vec′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷′</span></span> <span class="agda2-highlight-function">Vec→Vec′</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">Vec′→Vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">Vec′→Vec</span> <span class="agda2-highlight-inductive-constructor">[]′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">Vec′→Vec</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷′</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-function">Vec′→Vec</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">Vec′→Vec</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₂</span>
<span class="comment-delimiter">-- </span><span class="comment">This all is entirely standard except that the inductive occurrence in the type of
</span> <span class="comment-delimiter">-- </span><span class="comment">the second constructor is `Vec′A n` rather than `var n` or something similar.
</span>
<span class="comment-delimiter">-- </span><span class="comment">We can describe strictly positive data types which are not so easy to
</span><span class="comment-delimiter">-- </span><span class="comment">handle with usual descriptions. `Rose` e.g. is
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Positive</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Rose</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">rose</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Rose</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Rose</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">Rose′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Rose′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">μ′</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">Rose′A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">Rose′A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">rose′</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">rs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span> <span class="comment-delimiter">-- </span><span class="comment">I refuse to manually inline `map`.
</span> <span class="agda2-highlight-function">Rose→Rose′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Rose</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Rose′</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">Rose→Rose′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">rose</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">rose′</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">map</span> <span class="agda2-highlight-function">Rose→Rose′</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-function">Rose′→Rose</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Rose′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Rose</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">Rose′→Rose</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">rose′</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">rose</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">map</span> <span class="agda2-highlight-function">Rose′→Rose</span> <span class="agda2-highlight-bound-variable">rs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Rose′→Rose</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₁</span>
<span class="comment-delimiter">-- </span><span class="comment">In order to describe `Rose` in a safe-by-design way you need a rather complicated
</span> <span class="comment-delimiter">-- </span><span class="comment">machinery of indexed functors with multiple internal fixpoints ([6]) and
</span> <span class="comment-delimiter">-- </span><span class="comment">`List` must be described as well.
</span>
<span class="comment-delimiter">-- </span><span class="comment">But we can also describe non-strictly positive data types. Here is some HOAS:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">NonPositive</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">ι</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⇨_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Type</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NO_POSITIVITY_CHECK</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇨</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">app</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇨</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-bound-variable">τ</span>
<span class="agda2-highlight-function">Term′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Term′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">Term′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">τ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Term′</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Term′</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇨</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">τ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Term′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇨</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">Term′</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">lam′</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₀</span> <span class="agda2-highlight-symbol">(_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">app′</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₁</span> <span class="agda2-highlight-symbol">(_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-function">Term→Term′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term′</span> <span class="agda2-highlight-bound-variable">σ</span>
<span class="agda2-highlight-function">Term→Term′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam′</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term→Term′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Term′→Term</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">Term→Term′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">app</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">app′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Term→Term′</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Term→Term′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Term′→Term</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term′</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-bound-variable">σ</span>
<span class="agda2-highlight-function">Term′→Term</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">lam′</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term′→Term</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Term→Term′</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">Term′→Term</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">app′</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">app</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Term′→Term</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Term′→Term</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Term′→Term</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₂</span>
<span class="comment-delimiter">-- </span><span class="comment">And the final example: a described inductive-inductive data type:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">InductiveInductive</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infix</span> <span class="agda2-highlight-number">4</span> _∉_ _∉′_
<span class="comment-delimiter">-- </span><span class="comment">a `UList A` is a list, all elements of which are distinct.
</span> <span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">UList</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">UList</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-inductive-constructor">ucons</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∉</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">UList</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">_∉_</span></span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">UList</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">stop</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∉</span></span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≢</span></span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∉</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∉</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∉</span></span> <span class="agda2-highlight-inductive-constructor">ucons</span> <span class="agda2-highlight-bound-variable">p</span>
<span class="comment-delimiter">-- </span><span class="comment">In order to describe these data types we introduce the type of `Tag`s:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Tag</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">ulist</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Tag</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tag</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="comment-delimiter">-- </span><span class="comment">So we define `UListInn′` which is indexed by a `Tag A` and
</span> <span class="comment-delimiter">-- </span><span class="comment">describes both `UList` (the `ulist` tag) and `_∉_` (the `inn` tag).
</span> <span class="comment-delimiter">-- </span><span class="comment">Described `UList` is just `UList′ A = UListInn′ (ulist {A})`. `_∉′_` is similar.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The `inn` tag allows to instantiate `R` with anything,
</span> <span class="comment-delimiter">-- </span><span class="comment">but we always instantiate it with `UList A` in the constructors of `UListInn′`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Without descriptions it looks like this:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">NoDesc</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NO_POSITIVITY_CHECK</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Tag</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">[]′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">ulist</span>
<span class="agda2-highlight-inductive-constructor">ucons′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">ulist</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">ulist</span>
<span class="agda2-highlight-inductive-constructor">stop′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">ulist</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∋</span></span> <span class="agda2-highlight-inductive-constructor">[]′</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-inductive-constructor">keep′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">ulist</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≢</span></span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">UListInn′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">ucons′</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">))</span>
<span class="comment-delimiter">-- </span><span class="comment">And the direct encoding of the above data type is
</span>
<span class="agda2-highlight-function">UListInn′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tag</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">UListInn′</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span>
<span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">UListInn′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-inductive-constructor">ulist</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">[]′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">UListInn′</span> <span class="agda2-highlight-inductive-constructor">ulist</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">UListInn′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-inductive-constructor">ulist</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">ucons′</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">[]′</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">UListInn′</span> <span class="agda2-highlight-inductive-constructor">ulist</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≢</span></span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span>
<span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">UListInn′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">UListInn′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⇒</span></span>
<span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">ucons′</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)))</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="comment-delimiter">-- </span><span class="comment">Note that we use the constructors of `UListInn′` (`[]′` and `ucons′`) in the definition of
</span> <span class="comment-delimiter">-- </span><span class="comment">`UListInn′`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">`--type-in-type` is needed, because `Tag A` is too big and lies in `Set₁`,
</span> <span class="comment-delimiter">-- </span><span class="comment">but the actual `UList′ A` and `x ∉′ xs` are in `Set` like they should:
</span>
<span class="agda2-highlight-function">UList′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">UList′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">UListInn′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">ulist</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">})</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∉′_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">UList′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∉′</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">UListInn′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inn</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">[]′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₀</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">ucons′</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">stop′</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">keep′</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">#₃</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">The final test:
</span>
<span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-function">UList→UList′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">UList</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">UList′</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">UList→UList′</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]′</span>
<span class="agda2-highlight-function">UList→UList′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">ucons</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">ucons′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Inn→Inn′</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Inn→Inn′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∉</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∉′</span></span> <span class="agda2-highlight-function">UList→UList′</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">Inn→Inn′</span> <span class="agda2-highlight-inductive-constructor">stop</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">stop′</span>
<span class="agda2-highlight-function">Inn→Inn′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-bound-variable">q</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">keep′</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Inn→Inn′</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Inn→Inn′</span> <span class="agda2-highlight-bound-variable">q</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-function">UList′→UList</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">UList′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">UList</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">UList′→UList</span> <span class="agda2-highlight-inductive-constructor">[]′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">UList′→UList</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">ucons′</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">ucons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">UList′→UList</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">(_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">()))</span>
<span class="agda2-highlight-function">UList′→UList</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)))</span> <span class="agda2-highlight-symbol">(_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">()))</span>
<span class="agda2-highlight-function">UList′→UList</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₄</span>
<span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∉′</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∉</span></span> <span class="agda2-highlight-function">UList′→UList</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-inductive-constructor">stop′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">stop</span>
<span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">keep′</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-bound-variable">q</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-bound-variable">q</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">())</span>
<span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">()))</span>
<span class="agda2-highlight-function">Inn′→Inn</span> <span class="agda2-highlight-inductive-constructor">⟨⟩₄</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">References</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">[1] "Modeling Elimination of Described Types", Larry Diehl
</span> <span class="comment-delimiter">-- </span><span class="comment">http://spire-lang.org/blog/2014/01/15/modeling-elimination-of-described-types/
</span>
<span class="comment-delimiter">-- </span><span class="comment">[2] "Generic programming with ornaments and dependent types", Yorick Sijsling
</span> <span class="comment-delimiter">-- </span><span class="comment">http://sijsling.com/files/Thesis-YorickSijsling-color.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[3] "Deriving eliminators of described data types"
</span> <span class="comment-delimiter">-- </span><span class="comment">http://effectfully.blogspot.com/2016/06/deriving-eliminators-of-described-data.html
</span>
<span class="comment-delimiter">-- </span><span class="comment">[4] https://github.com/effectfully/Generic/blob/master/Examples/Experiment.agda
</span>
<span class="comment-delimiter">-- </span><span class="comment">[5] "Toy typechecker for Insanely Dependent Types", Ulf Norell
</span> <span class="comment-delimiter">-- </span><span class="comment">https://github.com/UlfNorell/insane/blob/694d5dcfdc3d4dd4f31138228ef8d87dd84fa9ec/Sigma.agda#L15
</span>
<span class="comment-delimiter">-- </span><span class="comment">[6] "Generic Programming with Indexed Functors", Andres Löh, José Pedro Magalhães
</span> <span class="comment-delimiter">-- </span><span class="comment">http://dreixel.net/research/pdf/gpif.pdf
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0tag:blogger.com,1999:blog-5131816758284711343.post-11128484862825653792016-07-31T09:19:00.002-07:002016-07-31T09:19:15.153-07:00Unbiased ornaments<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>UnOrn.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-record {
/* agda2-highlight-record-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">OPTIONS</span> <span class="comment">--type-in-type #-}
</span>
<span class="comment">-- In this post I'll shortly introduce ornaments and describe an "unbiased" version of them.
-- You might want to read some actual paper first (I recommend [1]).
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">UnOrn</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">0</span> _∸>_
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">6</span> _⊛_
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∸>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ι</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="comment">-- I'll be using the same representation of descriptions as in previous posts.
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⊛_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="comment">-- How are a description and its ornamented version related?
</span>
<span class="comment">-- 1. They both have the same amount of inductive occurrences.
-- Usually this rule sounds like "they both have the same tree structure", but we're going to
-- handle higher-order inductive occurrences which break this pattern.
</span>
<span class="comment">-- 2. An element of an ornamented data type can always be coerced to the corresponding
-- element of the original data type, i.e. vectors and sorted lists can be coerced to just lists.
</span>
<span class="comment">-- So when one data type can be coerced to another?
</span>
<span class="comment">-- 1. If the former simply contains more information that the latter.
-- We throw this information away and get lists from vectors.
</span>
<span class="comment">-- 2. If the former is an instance of the latter. Here is an example:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">InstExample</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Bool.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span>
<span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span>
<span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="comment">-- `D₀` is more general than `D₁` and hence `D₁` can be coerced to `D₀` (condition 2).
</span> <span class="comment">-- Besides, they have the same skeleton (condition 1): both have one non-recursive constructor,
</span> <span class="comment">-- so `D₁` is an ornamented version of `D₀`
</span>
<span class="comment">-- These are two standard first-order ornaments, but the `Desc` used in this post allows to
-- encode data types with higher-order inductive occurrences, so we have more ornaments as well.
</span>
<span class="comment">-- 3. If you drop an argument from a higher-inductive occurrence,
-- you'll get an ornamented data type. An example:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">RemoveExample</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Bool.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span>
<span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span>
<span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">b</span><span class="agda2-highlight-symbol">))</span>
<span class="comment">-- 4. If you add an argument to a higher-order inductive occurrence among with a value
-- from which the argument can be computed, you'll get an ornamented data type as well. An example:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">AddExample</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Bool.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span>
<span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">uncurry</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">replicate</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor">true</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">b</span><span class="agda2-highlight-symbol">)))</span>
<span class="comment">-- This might look silly, but here is how we can combine (2), (3) and (4) in a useful way:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Example</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Bool.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span>
<span class="comment">-- By (4):
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span>
<span class="comment">-- By `(A -> B × C) ≃ (A -> B) × (A -> C)`:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₂</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₂</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₂</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₂</span>
<span class="comment">-- By `(A × B -> C) ≃ (A -> B -> C)`:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₃</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₃</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₃</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₃</span>
<span class="comment">-- By (3):
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₄</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₄</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₄</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₄</span>
<span class="agda2-highlight-function">D₄→D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">D₄</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span>
<span class="agda2-highlight-function">D₄→D₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">C₄</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">D₄→D₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">b</span><span class="agda2-highlight-symbol">)))</span>
<span class="comment">-- Note that by (2) we can instantiate `Bool -> ℕ` to, say,
</span> <span class="comment">-- `λ b -> if b then 1 else 0` and thus get
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₅</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₅</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₅</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₅</span>
<span class="comment">-- which is therefore an ornamented version of `D₁`. This inference was a bit long: with
</span> <span class="comment">-- ornaments it's just "remove Bool; add ℕ".
</span>
<span class="comment">-- So here is how the usual "first-order-biased" ornaments look like
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Con</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Usual</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">_⁻¹_</span></span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">arg</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⁻¹</span></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">c</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">⁻¹</span></span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">c</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⊛_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">c</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">abst</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-bound-variable">D</span>
<span class="agda2-highlight-inductive-constructor">inst</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">drop</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">give</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-bound-variable">D</span>
<span class="comment">-- The first three constructors work in any context.
</span> <span class="comment">-- The next two work only in a first-order context.
</span> <span class="comment">-- The last two work only in a higher-order context.
</span>
<span class="comment">-- When coercing elements of ornamented data types, we of course need to coerce their indices
</span> <span class="comment">-- as well, so there is a `e : J -> I` that does this.
</span>
<span class="comment">-- `var` essentially receives a new index `j`, an old index `i` and a proof that `e j ≡ i`.
</span> <span class="comment">-- `keep` simply allows to go under a `π` without touching its content.
</span> <span class="comment">-- Same for `_⊛_`. The first ornament that `_⊛_` receives is always defined in
</span> <span class="comment">-- a higher-order context as it should.
</span>
<span class="comment">-- `abst` is for (1): it adds a new argument to a constructor.
</span> <span class="comment">-- `inst` is for (2): it instantiates some argument.
</span> <span class="comment">-- `drop` is for (3): it drops an argument to a higher-order inductive occurrence.
</span> <span class="comment">-- `give` is for (4): it adds a new argument to a higher-order inductive occurrence
</span> <span class="comment">-- and receives a value for it.
</span>
<span class="comment">-- Ornaments are interpreted as follows:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧ᵒ</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">c</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">J</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">arg</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">abst</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">inst</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">drop</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">give</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵒ</span></span>
<span class="comment">-- So `abst` and `give` add arguments and `inst` and `drop` remove them as expected.
</span>
<span class="comment">-- But look at the type signature of `drop`:
</span>
<span class="comment">-- drop : ∀ {A D} -> Orn e ho D -> Orn e ho (π A λ _ -> D)
</span>
<span class="comment">-- The second argument of `π` must always ignore its argument. I.e. if we have
</span>
<span class="comment">-- data D : Set where
</span> <span class="comment">-- C : (∀ n -> Fin n -> D) -> D
</span>
<span class="comment">-- we can't remove `n` even if we remove `Fin n` later too.
</span>
<span class="comment">-- `give x` has a similar defect: in a resulting description no type can depend on `x`.
</span>
<span class="comment">-- Here are unbiased ornaments that don't have these drawbacks:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-bound-variable">c</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">c</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⊛_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">D₁</span> <span class="agda2-highlight-bound-variable">D₂</span> <span class="agda2-highlight-bound-variable">E₁</span> <span class="agda2-highlight-bound-variable">E₂</span> <span class="agda2-highlight-bound-variable">c</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-bound-variable">D₁</span> <span class="agda2-highlight-bound-variable">E₁</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">D₂</span> <span class="agda2-highlight-bound-variable">E₂</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">D₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">E₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E₂</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">abst</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">inst</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">E</span>
<span class="agda2-highlight-inductive-constructor">drop</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">E</span>
<span class="agda2-highlight-inductive-constructor">give</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- The interpretation of an ornament now is simply the second description that `Orn` receives.
</span>
<span class="comment">-- Note how the `abst` and `drop` constructors are beautifully symmetric,
-- as well as the `inst` and `give` constructors.
</span>
<span class="comment">-- `drop` essentially says "you can use the removed "x" as soon as the final result
-- doesn't depend on it". And `give` receives an argument on which other types can depend.
</span>
<span class="comment">-- Here is a sanity check -- deriving from an ornament its algebra:
</span>
<span class="agda2-highlight-function">Alg</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Alg</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">ho</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-bound-variable">O</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">P</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">drop</span> <span class="agda2-highlight-bound-variable">O</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">give</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">O</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-bound-variable">O</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">P</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">forgetHyp</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">abst</span> <span class="agda2-highlight-bound-variable">O</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">inst</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">O</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">forgetAlg</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Alg</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">E</span>
<span class="agda2-highlight-function">forgetAlg</span> <span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">forgetExtend</span> <span class="agda2-highlight-bound-variable">O</span>
<span class="comment">-- `drop` removes an argument to a function, so to forget `drop` is to remember that binding.
-- `give` adds an argument and its value, so to forget `give` is to fill the argument with the value.
-- `abst` adds an argument to a constructor, so to forget `abst` is to simply ignore the argument.
-- `inst` specializes an argument to a constructor with some `x`, so to forget `inst` is to
-- apply the original constructor to `x`.
</span>
<span class="comment">-- Now having the usual catamorphisms stuff
</span>
<span class="agda2-highlight-function">mapHyp</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">mapHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">mapHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">mapHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">mapHyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">mapHyp</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">mapHyp</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">mapExtend</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">mapExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">q</span>
<span class="agda2-highlight-function">mapExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">mapExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">mapExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">mapHyp</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">mapExtend</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-function">gfold</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Alg</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">gfold</span> <span class="agda2-highlight-symbol">{</span>D <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">mapExtend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">gfold</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- We can define a generic forgetful map:
</span>
<span class="agda2-highlight-function">forget</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">O</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∸></span></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">forget</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">gfold</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">forgetAlg</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Tests</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">qvar</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">J</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">qvar</span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var</span>
<span class="comment">-- Ornamenting lists into vectors:
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Unit.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Bool.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<?>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">b</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><?></span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><?></span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊕_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><?></span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">5</span> _∷_ _∷ᵥ_
<span class="agda2-highlight-function">list</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">list</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">List</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">list</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷_</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷ᵥ_</span></span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">list→vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">list</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">list→vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">keep</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">$</span></span> <span class="agda2-highlight-inductive-constructor">var</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator"><?></span></span> <span class="agda2-highlight-inductive-constructor">abst</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">keep</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span>
<span class="comment">-- A simple test:
</span>
<span class="agda2-highlight-function">test</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">forget</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">list→vec</span> <span class="agda2-highlight-datatype">ℕ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-number">4</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-number">9</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-number">8</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-number">4</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">9</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">8</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">test</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment">-- A more contrived example:
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Fin</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-inductive-constructor">zero</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function">coe</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">coe</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">coe</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">coe</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">zero</span>
<span class="agda2-highlight-function">coh</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">coe</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">toℕ</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">coh</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">coh</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">()}</span>
<span class="agda2-highlight-function">coh</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">coh</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">cong</span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-function">coh</span>
<span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₁</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">coe</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">C₁</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-keyword">rewrite</span> <span class="agda2-highlight-function">coh</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">C₀</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">subst</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">D₀</span> <span class="agda2-highlight-symbol">_)</span> <span class="agda2-highlight-function">coh</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">D₁→D₀</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">toℕ</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))))</span>
<span class="comment">-- We remove `i : Fin m` in `D₀` on which an index depends and replace it with `n` on which
</span> <span class="comment">-- an index depends as well.
</span>
<span class="comment">-- And with encoded `D₀` and `D₁`:
</span>
<span class="agda2-highlight-function">d₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">d₀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">zero</span>
<span class="agda2-highlight-function">d₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">d₁</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function">d₁→d₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Orn</span> <span class="agda2-highlight-function">coe</span> <span class="agda2-highlight-inductive-constructor">fo</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">d₀</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function">d₁</span>
<span class="agda2-highlight-function">d₁→d₀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">drop</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">give</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">toℕ</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">qvar</span> <span class="agda2-highlight-function">coh</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-function">qvar</span> <span class="agda2-highlight-function">coh</span>
<span class="agda2-highlight-function">D₀′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">D₀′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">d₀</span>
<span class="agda2-highlight-function">D₁′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">D₁′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-function">d₁</span>
<span class="agda2-highlight-function">D₁′→D₀′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">D₁′</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">D₀′</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">coe</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">D₁′→D₀′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">forget</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">d₁→d₀</span> <span class="agda2-highlight-symbol">_)</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">References</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment">-- [1] "Ornamental Algebras, Algebraic Ornaments", Conor McBride
</span> <span class="comment">-- https://personal.cis.strath.ac.uk/conor.mcbride/pub/OAAO/LitOrn.pdf
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0tag:blogger.com,1999:blog-5131816758284711343.post-27633621123695726652016-07-21T02:26:00.001-07:002016-07-21T02:32:44.006-07:00Emulating cumulativity in Agda<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>Cumu.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-postulate {
/* agda2-highlight-postulate-face */
color: #0000cd;
}
.agda2-highlight-primitive {
/* agda2-highlight-primitive-face */
color: #0000cd;
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-record {
/* agda2-highlight-record-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
.comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="comment-delimiter">-- </span><span class="comment">In this post I'll show how to emulate cumulativity in Agda.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Cumu</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Level</span> <span class="agda2-highlight-keyword">renaming</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">zero</span> <span class="agda2-highlight-symbol">to</span> <span class="agda2-highlight-primitive">lzero</span><span class="agda2-highlight-symbol">;</span> <span class="agda2-highlight-primitive">suc</span> <span class="agda2-highlight-symbol">to</span> <span class="agda2-highlight-primitive">lsuc</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span>
<span class="comment-delimiter">-- </span><span class="comment">As an example let's take telescopes.
</span><span class="comment-delimiter">-- </span><span class="comment">Recall how they can be defined without universe polymophism:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Mono</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Unit.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Vec</span>
<span class="agda2-highlight-keyword">infix</span> <span class="agda2-highlight-number">3</span> _▷_
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">ε</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Tele</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_▷_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tele</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tele</span>
<span class="comment-delimiter">-- </span><span class="comment">`_▷_` receives a type `A` and the rest of a telescope,
</span> <span class="comment-delimiter">-- </span><span class="comment">where each type can depend on an element of type `A`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is an example:
</span>
<span class="agda2-highlight-function">example</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Tele</span>
<span class="agda2-highlight-function">example</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">ε</span>
<span class="comment-delimiter">-- </span><span class="comment">Each telescope represents the type of an n-ary tuples:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">ε</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span>
<span class="agda2-highlight-function">test</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-function">example</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">test</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">The problem with this encoding however is that `_▷_` always receives a `Set`,
</span> <span class="comment-delimiter">-- </span><span class="comment">while we want it to receive types from different universes. How can we achieve that?
</span>
<span class="comment-delimiter">-- </span><span class="comment">We could define `Tele` by recursion on a list of levels like this:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Rec</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Unit.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">_⊔_</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-primitive">lsuc</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-bound-variable">αs</span>
<span class="comment-delimiter">-- </span><span class="comment">This is the same `Tele` as above, but now universe polymorphic:
</span>
<span class="agda2-highlight-function">example</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-primitive">lzero</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">example</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="comment-delimiter">-- </span><span class="comment">The problem with this encoding however is that all levels are explictly reflected
</span> <span class="comment-delimiter">-- </span><span class="comment">at the type level (in this case they can be inferred, since `Tele` is constructor-headed).
</span> <span class="comment-delimiter">-- </span><span class="comment">It means that there can't exist telescopes with statically unknown length:
</span>
<span class="comment-delimiter">-- </span><span class="comment">fail : ∃ Tele
</span> <span class="comment-delimiter">-- </span><span class="comment">fail = ?
</span>
<span class="comment-delimiter">-- </span><span class="comment">((αs : List Level) → Set (foldr ((λ {.x} → _⊔_) ∘ lsuc) lzero αs))
</span> <span class="comment-delimiter">-- </span><span class="comment">!=< (_A_38 → Set _b_37)
</span> <span class="comment-delimiter">-- </span><span class="comment">because this would result in an invalid use of Setω
</span> <span class="comment-delimiter">-- </span><span class="comment">when checking that the expression Tele has type _A_38 → Set _b_37
</span>
<span class="comment-delimiter">-- </span><span class="comment">What we really want is to write `Tele (lsuc (lsuc lzero))`,
</span> <span class="comment-delimiter">-- </span><span class="comment">i.e. just one level -- the biggest -- and make Agda check that all other levels
</span> <span class="comment-delimiter">-- </span><span class="comment">are less or equal than it. And doesn't reflect the length of a telescope at the type level.
</span> <span class="comment-delimiter">-- </span><span class="comment">I.e. just what we normally do:
</span>
<span class="agda2-highlight-function">example₂</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set₂</span>
<span class="agda2-highlight-function">example₂</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">constructor</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="comment-delimiter">-- </span><span class="comment">We can state that one level is less or equal than another as follows:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_≤ℓ_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≤ℓ</span></span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">⊔</span></span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">β</span>
<span class="comment-delimiter">-- </span><span class="comment">I.e. if the maximum of `α` and `β` is `β`, then `α` is obviously less or equal than `β`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">We need a way to coerce a `Set α` to `Set β`, provided there is a proof of `α ≡ β`.
</span><span class="comment-delimiter">-- </span><span class="comment">It can be done either by a function:
</span>
<span class="agda2-highlight-function">Coerce′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span>
<span class="agda2-highlight-function">Coerce′</span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">id</span>
<span class="comment-delimiter">-- </span><span class="comment">or using a data type:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Coerce</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">coerce</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Coerce</span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="comment-delimiter">-- </span><span class="comment">We'll need both of them.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is the encoding finally:
</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NO_POSITIVITY_CHECK</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">ε</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-bound-variable">β</span>
<span class="agda2-highlight-inductive-constructor">cons</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≤ℓ</span></span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Coerce</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">cong</span> <span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-bound-variable">q</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-bound-variable">β</span>
<span class="comment-delimiter">-- </span><span class="comment">Operationally it's the same as before: `cons` receives a type `A` and the rest of a telescope,
</span><span class="comment-delimiter">-- </span><span class="comment">but now `A` lies in `Set α` and we have an explicit proof that `α` is less or equal than `β`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The type of `∃ λ (A : Set α) -> A -> Tele β` is `Set (lsuc α ⊔ lsuc β)` which is the same as
</span><span class="comment-delimiter">-- </span><span class="comment">`Set (lsuc (α ⊔ β))`, but it must lie in `Set (lsuc β)`, because the whole `Tele` lies there,
</span><span class="comment-delimiter">-- </span><span class="comment">so we coerce by `cong lsuc q : lsuc (α ⊔ β) ≡ lsuc β` and get the required type.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The constructor is recovered as
</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_▷_</span></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">cons</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">coerce</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">))</span>
<span class="comment-delimiter">-- </span><span class="comment">Though, it's not possible to use it in pattern matching,
</span><span class="comment-delimiter">-- </span><span class="comment">because that would force unification of `lsuc (α ⊔ β) =?= lsuc β`,
</span><span class="comment-delimiter">-- </span><span class="comment">which is an infinite equation that can't be solved.
</span>
<span class="comment-delimiter">-- </span><span class="comment">An example:
</span>
<span class="agda2-highlight-function">example</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-primitive">lzero</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">example</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">ε</span>
<span class="comment-delimiter">-- </span><span class="comment">All types lie in different universes and `Tele` receives only the level of the biggest universe.
</span>
<span class="comment-delimiter">-- </span><span class="comment">It only remains to interpret telescopes:
</span>
<span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧ᵀ</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">ε</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵀ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">cons</span> <span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵀ</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵀᵇ</span></span> <span class="agda2-highlight-bound-variable">q</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧ᵀᵇ</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-bound-variable">γ</span> <span class="agda2-highlight-bound-variable">q</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Coerce</span> <span class="agda2-highlight-symbol">{</span>β <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tele</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">≤ℓ</span></span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">coerce</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵀᵇ</span></span> <span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">Coerce′</span> <span class="agda2-highlight-bound-variable">q</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵀ</span></span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">It's the same as before, but we need two functions and one additional `Coerce′`.
</span><span class="comment-delimiter">-- </span><span class="comment">Two functions are needed, because, as was mentioned above, it's not possible to use `_▷_`
</span><span class="comment-delimiter">-- </span><span class="comment">in pattern matching, so the levels equation is generalized to `lsuc (α ⊔ β) =?= γ`,
</span><span class="comment-delimiter">-- </span><span class="comment">which can be solved. `Coerce′` is needed, because `∃ λ x -> ⟦ R x ⟧ᵀ` lies in `Set (α ⊔ β)`,
</span><span class="comment-delimiter">-- </span><span class="comment">while we want it to be in `Set β`. Note that `Coerce′` is just a function and
</span><span class="comment-delimiter">-- </span><span class="comment">doesn't introduce mess in the interpretation of a telescope.
</span>
<span class="comment-delimiter">-- </span><span class="comment">A simple test:
</span>
<span class="agda2-highlight-function">test</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-function">example</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵀ</span></span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">test</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">We have considered how to emulate cumulativity for telescopes,
</span><span class="comment-delimiter">-- </span><span class="comment">but there are other applications: convenient universe polymorphic descriptions
</span><span class="comment-delimiter">-- </span><span class="comment">(I'm working on a generic programming library that uses ideas described in this post),
</span><span class="comment-delimiter">-- </span><span class="comment">universe polymorphic Freer monads (as described by Kiselyov et al) for dealing with effects,
</span><span class="comment-delimiter">-- </span><span class="comment">perhaps something else.
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com3tag:blogger.com,1999:blog-5131816758284711343.post-36882284750654262922016-06-16T23:20:00.002-07:002016-07-21T02:32:36.325-07:00Deriving eliminators of described data types<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>Elim.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
.comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="comment-delimiter">-- </span><span class="comment">This posts describes how to derive eliminators of described data types.
</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">OPTIONS</span> <span class="comment-delimiter">--</span><span class="comment">type-in-type #-}
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">6</span> _⊛_
<span class="comment-delimiter">-- </span><span class="comment">I'll be using the form of descriptions introduced in the previous post:
</span><span class="comment-delimiter">-- </span><span class="comment">http://effectfully.blogspot.com/2016/04/descriptions.html
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⊛_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="comment-delimiter">-- </span><span class="comment">It is crucial to define `μ` as a `data` and not as an inductive `record`,
</span><span class="comment-delimiter">-- </span><span class="comment">because termination checker works better with `data`s.
</span>
<span class="comment-delimiter">-- </span><span class="comment">While defining the generic `elim` function, we'll be keeping in mind some
</span><span class="comment-delimiter">-- </span><span class="comment">described constructor. Let it be `_∷_` for vectors:
</span>
<span class="comment-delimiter">-- </span><span class="comment">`cons-desc = π ℕ λ n -> π A λ _ -> var n ⊛ var (suc n)`
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Verbose</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">How to get the actual type of the constructor from this description?
</span> <span class="comment-delimiter">-- </span><span class="comment">Each `π` correspons to some `->` and each `_⊛_` corresponds to it as well.
</span> <span class="comment-delimiter">-- </span><span class="comment">I.e. the actual type is `(n : ℕ) -> A -> Vec A n -> Vec (suc n)`.
</span> <span class="comment-delimiter">-- </span><span class="comment">After generalizing `Vec A` to `B`, we get the following definition:
</span>
<span class="agda2-highlight-function">Cons</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Cons</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">Cons</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Cons</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Cons</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Cons</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">E</span>
<span class="comment-delimiter">-- </span><span class="comment">`Cons B cons-desc` evaluates to `(n : ℕ) -> A -> B n -> B (suc n)` as required.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Eliminator of `_∷_` (with `Vec A` generalized to `B`) looks like this:
</span>
<span class="comment-delimiter">-- </span><span class="comment">`(n : ℕ) -> (x : A) -> {xs : B n} -> P xs -> P (x ∷ xs)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">so we need to eliminate `cons-desc` again, but now with `_∷_ : Cons B cons-desc` provided
</span> <span class="comment-delimiter">-- </span><span class="comment">(to form the final `P (x ∷ xs)` part). Note that each inductive occurrence in a description
</span> <span class="comment-delimiter">-- </span><span class="comment">becomes replaced by the corresponding induction hypothesis, hence the `_⊛_` case
</span> <span class="comment-delimiter">-- </span><span class="comment">in the function below:
</span>
<span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Cons</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">The type of `P` is `(D : Desc I) -> ⟦ D ⟧ B -> Set` instead of `∀ {i} -> B i -> Set`,
</span> <span class="comment-delimiter">-- </span><span class="comment">because there can be a higher-order inductive occurrence (like in `W`) and
</span> <span class="comment-delimiter">-- </span><span class="comment">the induction hypothesis have to be computed by induction on a `Desc`.
</span> <span class="comment-delimiter">-- </span><span class="comment">We'll do this in a moment.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The next step is to compute the constructor.
</span> <span class="comment-delimiter">-- </span><span class="comment">As described in the previous post the actual `_∷_` can be recovered as
</span>
<span class="comment-delimiter">-- </span><span class="comment">`_∷_ {n} x xs = node (n , x , xs , refl)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">(it's `node (false, n , x , xs , refl)` for the actual `Vec`,
</span> <span class="comment-delimiter">-- </span><span class="comment">because the first element in a tuple allows to distinguish `[]` and `_∷_`)
</span>
<span class="comment-delimiter">-- </span><span class="comment">So all we need is to define a function that receives `n` arguments,
</span> <span class="comment-delimiter">-- </span><span class="comment">puts them in a tuple and applies `node` to it. That's the usual CPS stuff:
</span>
<span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Cons</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">D</span>
<span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_,_</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">cons</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_,_</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">However note that `ElimBy` and `cons` are defined by the same induction on `D`.
</span> <span class="comment-delimiter">-- </span><span class="comment">Hence we can drop `Cons` and `cons` stuff and compute `ElimBy` directly.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is the final definition of `ElimBy`:
</span>
<span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_,_</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_,_</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">Now we need to compute induction hypotheses. Recall how `W` looks like:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">W</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">sup</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">W</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">W</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span>
<span class="comment-delimiter">-- </span><span class="comment">Its eliminator is
</span>
<span class="agda2-highlight-function">elimW</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">W</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">W</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">sup</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">g</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">w</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">w</span>
<span class="agda2-highlight-function">elimW</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">sup</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">g</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">elimW</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">))</span>
<span class="comment-delimiter">-- </span><span class="comment">I.e. the induction hypothesis for higher-order `g : B x -> W A B` is
</span><span class="comment-delimiter">-- </span><span class="comment">`(y : B x) -> P (g y)` (higher-order as well).
</span>
<span class="agda2-highlight-function">Hyp</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Hyp</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">Hyp</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Hyp</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Hyp</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">Hyp</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">Hyp</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="comment-delimiter">-- </span><span class="comment">When an inductive occurrence is a tuple, the induction hypothesis is a tuple too,
</span><span class="comment-delimiter">-- </span><span class="comment">hence the `_⊛_` case above.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Finally, the type of a function that eliminator receives
</span><span class="comment-delimiter">-- </span><span class="comment">(I'll call it "an eliminating function") is
</span>
<span class="agda2-highlight-function">Elim</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Elim</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">ElimBy</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">Hyp</span>
<span class="comment-delimiter">-- </span><span class="comment">It only remains to construct the actual generic eliminator.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">_</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">D₀</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D₀</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Elim</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">D₀</span> <span class="agda2-highlight-inductive-constructor">node</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-function">elimExtend</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D₀</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D₀</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Elim</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">k</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">e</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D₀</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">elimExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">z</span>
<span class="agda2-highlight-function">elimExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">elimExtend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">d</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimExtend</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">hyp</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">d</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="agda2-highlight-function">hyp</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">d</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D₀</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Hyp</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">d</span>
<span class="agda2-highlight-function">hyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">d</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elim</span> <span class="agda2-highlight-bound-variable">d</span>
<span class="agda2-highlight-function">hyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">hyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">hyp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">hyp</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">hyp</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">elim</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">d</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-bound-variable">D₀</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">d</span>
<span class="agda2-highlight-function">elim</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-bound-variable">e</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimExtend</span> <span class="agda2-highlight-bound-variable">D₀</span> <span class="agda2-highlight-bound-variable">h</span> <span class="agda2-highlight-bound-variable">e</span>
<span class="comment-delimiter">-- </span><span class="comment">No surpise we need a family of mutually defined functions.
</span><span class="comment-delimiter">-- </span><span class="comment">`D₀` is the description of a data being eliminated. It's in the module parameter
</span><span class="comment-delimiter">-- </span><span class="comment">among with `P` and an eliminating function `h`, because otherwise it would be required
</span><span class="comment-delimiter">-- </span><span class="comment">to trace them explicitly through all three functions and these parameters never change.
</span>
<span class="comment-delimiter">-- </span><span class="comment">`elim` unfolds a `μ` and delegates the work to `elimExtend`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">`elimExtend` is defined by induction on `D`:
</span><span class="comment-delimiter">-- </span><span class="comment">- At the end of a description we simply return what has been computed so far.
</span><span class="comment-delimiter">-- </span><span class="comment">- On encountering a non-inductive argument to a constructor we
</span><span class="comment-delimiter">-- </span><span class="comment">apply the eliminating function to it.
</span><span class="comment-delimiter">-- </span><span class="comment">- On encountering an inductive argument to a constructor we
</span><span class="comment-delimiter">-- </span><span class="comment">compute recursively (`hyp` calls `elim` in the `var` case) and
</span><span class="comment-delimiter">-- </span><span class="comment">apply the elimination function to the result of the computation.
</span>
<span class="comment-delimiter">-- </span><span class="comment">That's basically it. An example:
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Bool.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_<?>_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">b</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><?></span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><?></span></span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊕_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><?></span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">μ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷_</span></span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elim</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator"><?></span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">Since vectors have two constructors, `vec` starts with `π Bool` which allows to split
</span><span class="comment-delimiter">-- </span><span class="comment">the description into two parts: the one that describes `[]` and the other that describes `_∷_`.
</span><span class="comment-delimiter">-- </span><span class="comment">That's why an eliminating function for vectors is of the form `(b : Bool) -> ...` and
</span><span class="comment-delimiter">-- </span><span class="comment">we use `_<?>_` to choose between an eliminating function for `[]` (just a value `z`) and
</span><span class="comment-delimiter">-- </span><span class="comment">an eliminating function for `_∷_` (which ignores `n : ℕ`).
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0tag:blogger.com,1999:blog-5131816758284711343.post-73399590225250458142016-04-27T01:49:00.002-07:002016-04-27T02:01:27.813-07:00Descriptions<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>Desc.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-field {
/* agda2-highlight-field-face */
color: #ee1289;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-record {
/* agda2-highlight-record-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="comment">-- In this post I'll shortly introduce descriptions and describe a variant of them that I prefer.
-- If you haven't seen this form of generic programming before,
-- you might want to start with something simpler first:
-- http://effectfully.blogspot.com/2016/02/simple-generic-programming.html
</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">OPTIONS</span> <span class="comment">--type-in-type --no-termination-check #-}
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Desc</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Empty</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Unit.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Bool.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Computational</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment">-- I'll start by defining descriptions in their usual computational form.
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">ind</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">κ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⊛_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">ind</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">κ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span>
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">inductive</span>
<span class="agda2-highlight-keyword">constructor</span> <span class="agda2-highlight-inductive-constructor">node</span>
<span class="agda2-highlight-keyword">field</span> <span class="agda2-highlight-field">knot</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-bound-variable">F</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- `ind i` is an inductive position. `⟦ ind i ⟧ (μ F)` reduces to `μ F i`,
</span> <span class="comment">-- so that is where knot tying happens. In `μ F j` `j` is the index of a term
</span> <span class="comment">-- and in `ind i` `i` is the index of a subterm.
</span>
<span class="comment">-- `κ` allows to embed any `Set` into a description.
</span> <span class="comment">-- `σ` allows this too, but `κ` is non-recursive and thus can finish a description.
</span>
<span class="comment">-- `σ` serves two purposes:
</span> <span class="comment">-- 1. It allows to split a description of a data type into descriptions of several constructors.
</span> <span class="comment">-- E.g. we can express the fact that a data type has two constructors by defining its
</span> <span class="comment">-- description as `σ Bool λ b -> if b then cons₁ else cons₂` for some `cons₁` and `cons₂`.
</span> <span class="comment">-- 2. It encodes top-level Π-types in the type of a constructor in a target language.
</span> <span class="comment">-- I'll explain in a minute why we use `σ` to encode `Π`.
</span>
<span class="comment">-- `π` is for higher-order inductive occurrences. I.e. for data types where an inductive
</span> <span class="comment">-- position appears to the right of the arrow. E.g. `W`:
</span>
<span class="comment">-- data W (A : Set) (B : A -> Set) : Set where
</span> <span class="comment">-- sup : (x : A) -> (B x -> W A B) -> W A B
</span>
<span class="comment">-- or `Desc` itself (the `σ` and `π`) constructors.
</span>
<span class="comment">-- `D ⊛ E` is a first-order equivalent of `π Bool λ b -> if b then D else E`.
</span>
<span class="comment">-- The choice operator mentioned above:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊕_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">if</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">then</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">else</span></span> <span class="agda2-highlight-bound-variable">E</span>
<span class="comment">-- Here is an example of described data type.
</span>
<span class="agda2-highlight-function">list</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">list</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">κ</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">ind</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">List</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">list</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="comment">-- Lists are a non-indexed data type, hence we pass `⊤` to `Desc`, and
</span> <span class="comment">-- lists have two constructors: the one that doesn't contain any data
</span> <span class="comment">-- (which is expressed as `κ ⊤`) and the other that contains an `A` and an inductive occurrence.
</span>
<span class="comment">-- The recovered constructors:
</span>
<span class="comment">-- [] : ∀ {A} -> List A
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- _∷_ : ∀ {A} -> A -> List A -> List A
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷_</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- Now we can see why `σ` is used to describe the arguments to a constructor.
</span> <span class="comment">-- If we define `List` via the `data` keyword, then `_∷_` is a "god-given" function,
</span> <span class="comment">-- but internally it's just a tag "cons" stored among with an element and a sublist.
</span> <span class="comment">-- Here we store the element and the sublist explicitly.
</span>
<span class="comment">-- You can read described constructors like there is `-> D` after them,
</span> <span class="comment">-- where `D` is the data type being described. E.g. for the usual lists `_∷_` can be defined as
</span>
<span class="comment">-- `cons : (A × List A) -> List A`
</span>
<span class="comment">-- which is the same as
</span>
<span class="comment">-- `cons : (Σ A λ _ -> List A) -> List A`.
</span>
<span class="comment">-- compare this to `_∷_` described above: `σ A λ _ -> ind tt`.
</span>
<span class="comment">-- Described lists have the usual eliminator.
</span>
<span class="agda2-highlight-function">elimList</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">elimList</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">z</span>
<span class="agda2-highlight-function">elimList</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">elimList</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- Now let's describe something indexed.
</span>
<span class="agda2-highlight-function">fin</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">fin</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">κ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">ind</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Fin</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Fin</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-function">fin</span>
<span class="comment">-- fzero : ∀ {n} -> Fin (suc n)
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">fzero</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- fsuc : ∀ {n} -> Fin n -> Fin (suc n)
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">fsuc</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- `Fin` has two constructors and in order to describe them we must introduce explicit
</span> <span class="comment">-- unification constraints. `Fin n` is inhabited only when `n ≡ suc m` for some `m` --
</span> <span class="comment">-- that's what the description says. Since the unification constraint is the same for
</span> <span class="comment">-- both constructors, we could introduce it before defining actual constructors:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Before</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">fin′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">fin′</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">κ</span> <span class="agda2-highlight-record">⊤</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-inductive-constructor">ind</span> <span class="agda2-highlight-bound-variable">m</span>
<span class="agda2-highlight-function">Fin′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Fin′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-function">fin′</span>
<span class="agda2-highlight-function">fzero′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Fin′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">fzero′</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">fsuc′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Fin′</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Fin′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">fsuc′</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- `Fin` has the usual induction principle:
</span>
<span class="agda2-highlight-function">elimFin</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Fin</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Fin</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">fsuc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">fzero</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Fin</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">elimFin</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor">fzero</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">elimFin</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">fsuc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">elimFin</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- But these explicit unification constraints are quite ugly.
</span> <span class="comment">-- Moreover, sometimes you want to have access to them while defining generic functions
</span> <span class="comment">-- over `Desc`, but constraints can appear everywhere in the definition of a description,
</span> <span class="comment">-- so you can't locate them by just pattern matching on a `Desc`.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Propositional</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment">-- So here are propositional descriptions that solve most of the problems mentioned above.
</span> <span class="comment">-- I'm taking stuff directly from [1].
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">ind</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">hind</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">ret</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">σ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">ind</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">hind</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">inductive</span>
<span class="agda2-highlight-keyword">constructor</span> <span class="agda2-highlight-inductive-constructor">node</span>
<span class="agda2-highlight-keyword">field</span> <span class="agda2-highlight-field">knot</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="comment">-- Each desciption ends with `ret` that receives the index of a term.
</span> <span class="comment">-- `σ` is the same thing as before.
</span> <span class="comment">-- `ind` carries an inductive position and the rest of a description.
</span> <span class="comment">-- `hind` is the same thing as `ind`, but an inductive occurrence is higher-order.
</span>
<span class="comment">-- `Extend` is straightforward and pretty linear. The only interesting case is `ret`:
</span> <span class="comment">-- that's where we put constraints. Now we don't need to write them down explicitly.
</span>
<span class="comment">-- However I don't like the `(A -> I)` part in `hind`. If we want to encode something like
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Foo</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">foo</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Foo</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Foo</span>
<span class="comment">-- then `A` must be `ℕ × Bool` and this compulsory uncurrying is annoying.
</span> <span class="comment">-- Manual extraction of elements from a big tuple is verbose and ugly.
</span>
<span class="comment">-- To encode this definition
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Bar</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">foo</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Bar</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-datatype">Bar</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Bar</span>
<span class="comment">-- we have to transform it to
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Bar′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">foo</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Bar′</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Bar′</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Bar′</span>
<span class="comment">-- Computational descriptions didn't have these problems.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">CompProp</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">6</span> _⊛_
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">5</span> _⊕_
<span class="comment">-- So here is a compact and convenient form of descriptions:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⊛_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">∃</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">inductive</span>
<span class="agda2-highlight-keyword">constructor</span> <span class="agda2-highlight-inductive-constructor">node</span>
<span class="agda2-highlight-keyword">field</span> <span class="agda2-highlight-field">knot</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Extend</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-bound-variable">D</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="comment">-- `⟦_⟧` is taken from computational descriptions and
</span> <span class="comment">-- `Extend` is taken from propositional descriptions.
</span>
<span class="comment">-- `var` serves as both `ind` and `ret`. There is `var i` at the end of each constructor,
</span> <span class="comment">-- where `i` is the index that a constructor returns. All other `var`s in a description
</span> <span class="comment">-- represent inductive positions.
</span>
<span class="comment">-- `π` subsumes both `σ` and `π` from computation descriptions.
</span> <span class="comment">-- `Extend` interprets `π` as `∃` and `⟦_⟧` interprets `π` as `Π`.
</span>
<span class="comment">-- Note that `μ` in this representation and in the propositional one receives a proper
</span> <span class="comment">-- first-order `Desc`, while in the computational representation `μ` receives a
</span> <span class="comment">-- higher-order `I -> Desc I`.
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊕_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">if</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">then</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">else</span></span> <span class="agda2-highlight-bound-variable">E</span>
<span class="comment">-- Everything should become clear after looking at an example:
</span>
<span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊕</span></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">vec</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- Vectors have two constructors: the one that doesn't contain any data and
</span> <span class="comment">-- the other that carries an `A` and a subvector `xs : Vec A n`.
</span> <span class="comment">-- The former constructor returns a vector of length `0` and
</span> <span class="comment">-- the latter returns a vector of length `suc n`.
</span> <span class="comment">-- Compare this to the usual definition of vectors which has the same pattern:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">UsualVec</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Vec′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Vec′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- `Extend` interprets `π` as `∃`, i.e. like `⟦_⟧` in computational descriptions interprets `σ`,
</span> <span class="comment">-- so the recovered constructors are very similar:
</span>
<span class="comment">-- [] : ∀ {A} -> Vec A 0
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- _∷_ : ∀ {n A} -> A -> Vec A n -> Vec A (suc n)
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷_</span></span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">false</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">z</span>
<span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- Let's now encode `W`:
</span>
<span class="agda2-highlight-function">w</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">w</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-function">W</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">W</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">w</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="comment">-- sup : ∀ {A B} -> (x : A) -> (B x -> W A B) -> W A B
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">sup</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- The key thing here is that `Extend` interprets `D` and `E` in `D ⊛ E` differently.
</span> <span class="comment">-- In `D` `π` encodes actual `Π` and `var i` is an inductive position.
</span> <span class="comment">-- In `E` `π` encodes `∃` and `var i` (if it's not to the left of another `_⊛_`)
</span> <span class="comment">-- represents the index that a constructor returns.
</span>
<span class="comment">-- Compare this to the usual definion of `W`:
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">UsualW</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">W′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">sup′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">W′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">W′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span>
<span class="comment">-- They are quite the same except that `_⊛_` is replaced by `_->_`.
</span>
<span class="comment">-- As the final example we can encode `Desc` itself:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Codes</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">varᶜ</span> <span class="agda2-highlight-inductive-constructor">πᶜ</span> <span class="agda2-highlight-inductive-constructor">⊛ᶜ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Codes</span>
<span class="agda2-highlight-function">desc</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-datatype">Codes</span> <span class="agda2-highlight-symbol">λ</span>
<span class="agda2-highlight-symbol">{</span> <span class="agda2-highlight-inductive-constructor">varᶜ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-symbol">;</span> <span class="agda2-highlight-inductive-constructor">πᶜ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-symbol">;</span> <span class="agda2-highlight-inductive-constructor">⊛ᶜ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-function">Desc′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Desc′</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">μ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">desc</span> <span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">tt</span>
<span class="comment">-- var′ : ∀ {I} -> I -> Desc′ I
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">var′</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">varᶜ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- π′ : ∀ {I} A -> (A -> Desc′ I) -> Desc′ I
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">π′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">πᶜ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- _⊛′_ : ∀ {I} -> Desc′ I -> Desc′ I -> Desc′ I
</span> <span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⊛′_</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">⊛ᶜ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">E</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">refl</span><span class="agda2-highlight-symbol">)</span>
<span class="comment">-- `Desc` and `Desc′` are clearly isomorphic:
</span>
<span class="agda2-highlight-function">fromDesc</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Desc′</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-function">fromDesc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var′</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">fromDesc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">fromDesc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">fromDesc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">fromDesc</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛′</span></span> <span class="agda2-highlight-function">fromDesc</span> <span class="agda2-highlight-bound-variable">E</span>
<span class="agda2-highlight-function">toDesc</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Desc′</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Desc</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-function">toDesc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var′</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">i</span>
<span class="agda2-highlight-function">toDesc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">π′</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">π</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">toDesc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">toDesc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛′</span></span> <span class="agda2-highlight-bound-variable">E</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">toDesc</span> <span class="agda2-highlight-bound-variable">D</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-function">toDesc</span> <span class="agda2-highlight-bound-variable">E</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">References</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment">-- [1] "Modeling Elimination of Described Types"
</span> <span class="comment">-- Larry Diehl
</span> <span class="comment">-- http://spire-lang.org/blog/2014/01/15/modeling-elimination-of-described-types/
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0tag:blogger.com,1999:blog-5131816758284711343.post-10602192188482480092016-04-10T06:19:00.001-07:002016-07-21T02:32:52.008-07:00Generic universe polymorphic programming. Part two<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>Poly.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-field {
/* agda2-highlight-field-face */
color: #ee1289;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-postulate {
/* agda2-highlight-postulate-face */
color: #0000cd;
}
.agda2-highlight-primitive {
/* agda2-highlight-primitive-face */
color: #0000cd;
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-record {
/* agda2-highlight-record-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
.comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="comment-delimiter">-- </span><span class="comment">This blog post is about universe polymorphic programming in Agda.
</span><span class="comment-delimiter">-- </span><span class="comment">The first part can be found here:
</span><span class="comment-delimiter">-- </span><span class="comment">[1] http://stackoverflow.com/questions/29179508/arity-generic-programming-in-agda
</span><span class="comment-delimiter">-- </span><span class="comment">I'll describe how to treat dependent and non-dependent universe polymorphic telescopes
</span><span class="comment-delimiter">-- </span><span class="comment">more or less uniformly, but to me it looks like a puzzle that is not anyhow important.
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Level</span> <span class="agda2-highlight-keyword">renaming</span> <span class="agda2-highlight-symbol">(</span>zero <span class="agda2-highlight-symbol">to</span> lzero<span class="agda2-highlight-symbol">;</span> suc <span class="agda2-highlight-symbol">to</span> lsuc<span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Empty</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span>_⊔_<span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Fin</span> <span class="agda2-highlight-keyword">using</span> <span class="agda2-highlight-symbol">(</span>Fin<span class="agda2-highlight-symbol">;</span> zero<span class="agda2-highlight-symbol">;</span> suc<span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Sum</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span>map<span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span>map<span class="agda2-highlight-symbol">;</span> zip<span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">Nil</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">constructor</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="comment-delimiter">-- </span><span class="comment">We start by defining η-friendly vectors.
</span>
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">6</span> _^_
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_^_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span>
<span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Nil</span>
<span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span>
<span class="comment-delimiter">-- </span><span class="comment">The difference between `A ^ n` and `Vec A n` is that `A ^ n` can be inferred pointwise.
</span><span class="comment-delimiter">-- </span><span class="comment">Here is an example.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Difference</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Unit.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Vec</span>
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">Infer</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">The type signatures of `infer-vec` and `infer-pow` suggest that
</span> <span class="comment-delimiter">-- </span><span class="comment">if the first and the second elements of a two element vector can be inferred,
</span> <span class="comment-delimiter">-- </span><span class="comment">then the whole vector can be inferred.
</span>
<span class="agda2-highlight-function">infer-pow</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-number">2</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Infer</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₁</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Infer</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-field">proj₂</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">infer-pow</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">infer-vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">p</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-number">2</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Infer</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">head</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Infer</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">head</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">tail</span> <span class="agda2-highlight-bound-variable">p</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">infer-vec</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">infer0</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-record">Infer</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function">infer0</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">infer1</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-record">Infer</span> <span class="agda2-highlight-number">1</span>
<span class="agda2-highlight-function">infer1</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">_</span>
<span class="comment-delimiter">-- </span><span class="comment">This is true for our η-friendly vectors:
</span>
<span class="agda2-highlight-function">ok-infer-pow</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-record">⊤</span>
<span class="agda2-highlight-function">ok-infer-pow</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">infer-pow</span> <span class="agda2-highlight-function">infer0</span> <span class="agda2-highlight-function">infer1</span>
<span class="comment-delimiter">-- </span><span class="comment">But for usual vectors results in unsolved metas:
</span>
<span class="comment-delimiter">-- </span><span class="comment">fail-infer-vec : ⊤
</span> <span class="comment-delimiter">-- </span><span class="comment">fail-infer-vec = infer-vec infer0 infer1
</span>
<span class="comment-delimiter">-- </span><span class="comment">_p_72 : Vec ℕ 2
</span> <span class="comment-delimiter">-- </span><span class="comment">_73 : Infer (head _p_72)
</span> <span class="comment-delimiter">-- </span><span class="comment">_75 : Infer (head (tail _p_72))
</span>
<span class="comment-delimiter">-- </span><span class="comment">Since we're going to use vectors to store levels which should be inferred,
</span> <span class="comment-delimiter">-- </span><span class="comment">it's natural to make these vectors η-friendly.
</span> <span class="comment-delimiter">-- </span><span class="comment">Though, this is not really necessarily in most cases.
</span>
<span class="comment-delimiter">-- </span><span class="comment">A universe dependent eliminator for `_^_` (I've never encountered such a thing in nature):
</span>
<span class="agda2-highlight-function">elimPow</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">elimPow</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">z</span>
<span class="agda2-highlight-function">elimPow</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">elimPow</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">Some basic functions on `_^_`:
</span>
<span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimPow</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">map</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">map</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">(_</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^_</span></span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_,_</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">foldr₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">foldr₁</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">foldr₁</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr₁</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">And level-specific ones:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊔ⁿ_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊔ⁿ_</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">flip</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">$</span></span> <span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">_⊔_</span></span>
<span class="agda2-highlight-function">max</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span>
<span class="agda2-highlight-function">max</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊔ⁿ</span></span> <span class="agda2-highlight-primitive">lzero</span>
<span class="comment-delimiter">-- </span><span class="comment">`(lsuc lzero , lzero , lift tt) ⊔ⁿ lsuc (lsuc lzero)` reduces to
</span><span class="comment-delimiter">-- </span><span class="comment">`lsuc lzero ⊔ lzero ⊔ lsuc (lsuc lzero)` (modulo associativity, but Agda has a
</span><span class="comment-delimiter">-- </span><span class="comment">special treatment of level expression, so associativity doesn't matter).
</span>
<span class="comment-delimiter">-- </span><span class="comment">We are now ready to define the type of heterogeneous lists of `Set`s:
</span>
<span class="agda2-highlight-function">Sets′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">max</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">Sets′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimPow</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">max</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)))</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-record">Nil</span>
<span class="comment-delimiter">-- </span><span class="comment">I.e. turn each `α` in `αs` into `Set α` and fold the resulting list with `_×_`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">An example:
</span>
<span class="agda2-highlight-function">ex-sets</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Sets′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">ex-sets</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="comment-delimiter">-- </span><span class="comment">The type of telescopes (`Sets` at the link in the first paragraph of this post)
</span><span class="comment-delimiter">-- </span><span class="comment">can be defined as
</span>
<span class="agda2-highlight-function">Tele′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">max</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">Tele′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimPow</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">max</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)))</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-record">Nil</span>
<span class="comment-delimiter">-- </span><span class="comment">It has the same pattern as `Sets′`, but latter elements can depend on former in `Tele′`. E.g.
</span>
<span class="agda2-highlight-function">ex-tele</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Tele′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">ex-tele</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="comment-delimiter">-- </span><span class="comment">There is a clear pattern: both `Sets′` and `Tele′` are instances of something like
</span>
<span class="comment-delimiter">-- </span><span class="comment">`TeleBy′ F = elimPow (Setₘ lsuc) (λ α R -> Σ (Set α) λ A -> F A R) Nil`
</span>
<span class="comment-delimiter">-- </span><span class="comment">with
</span>
<span class="comment-delimiter">-- </span><span class="comment">`Sets′ = TeleBy′ (λ A R -> R)`
</span><span class="comment-delimiter">-- </span><span class="comment">`Tele′ = TeleBy′ (λ A R -> A -> R)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">But note that universe polymorphic `(λ A R -> R)` and `(λ A R -> A -> R)` have different types:
</span>
<span class="agda2-highlight-function">SetsF</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ρ</span>
<span class="agda2-highlight-function">SetsF</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">R</span>
<span class="agda2-highlight-function">TeleF</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">⊔</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">TeleF</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">R</span>
<span class="comment-delimiter">-- </span><span class="comment">`Set ρ` versus `Set (α ⊔ ρ)`. Hence we need to make `TeleBy′` slightly more generic
</span>
<span class="agda2-highlight-function">TeleBy′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">_</span>
<span class="agda2-highlight-function">TeleBy′</span> <span class="agda2-highlight-symbol">{</span>f <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimPow</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">⊔</span></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">R</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-record">Nil</span>
<span class="comment-delimiter">-- </span><span class="comment">Now both `Sets′` and `Tele′` can be defined in terms of `TeleBy′`.
</span><span class="comment-delimiter">-- </span><span class="comment">But sadly, it's not clear to Agda that `TeleBy′` is constructor-headed,
</span><span class="comment-delimiter">-- </span><span class="comment">so she can't infer `αs` when a `Tele′ F αs` is provided.
</span><span class="comment-delimiter">-- </span><span class="comment">This breaks inference and hence we are forced to define `TeleBy` by explicit induction:
</span>
<span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">⊔</span></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Nil</span>
<span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Σ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">As promised, the definitions of `Sets` and `Tele` are
</span>
<span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">_⊔_</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-primitive">lsuc</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-function">SetsF</span>
<span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">_⊔_</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-primitive">lsuc</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-function">TeleF</span>
<span class="comment-delimiter">-- </span><span class="comment">`Sets` can be mapped over.
</span>
<span class="agda2-highlight-function">mapSets</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">map</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">mapSets</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">mapSets</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">mapSets</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">R</span>
<span class="comment-delimiter">-- </span><span class="comment">Since we have heterogeneous lists of types, we can define heterogeneous lists of values over them.
</span>
<span class="agda2-highlight-function">HList</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">max</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">HList</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Nil</span>
<span class="agda2-highlight-function">HList</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-function">HList</span> <span class="agda2-highlight-bound-variable">R</span>
<span class="comment-delimiter">-- </span><span class="comment">An example:
</span>
<span class="agda2-highlight-function">ex-hlist</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">HList</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">ex-hlist</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="comment-delimiter">-- </span><span class="comment">As an example of a function defined on heterogeneous lists consider the `lookupʰ` function:
</span>
<span class="agda2-highlight-function">lookup</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">lookup</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">lookup</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">lookup</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">lookupˢ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">lookup</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">lookupˢ</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">lookupˢ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">R</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">lookupˢ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">R</span>
<span class="agda2-highlight-function">lookupʰ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">HList</span> <span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">lookupˢ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">As</span>
<span class="agda2-highlight-function">lookupʰ</span> <span class="agda2-highlight-inductive-constructor">zero</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">lookupʰ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">i</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">lookupʰ</span> <span class="agda2-highlight-bound-variable">i</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="comment-delimiter">-- </span><span class="comment">A test:
</span>
<span class="agda2-highlight-function">test-lookupʰ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">lookupʰ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-inductive-constructor">zero</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-function">ex-hlist</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">test-lookupʰ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">`Sets` is the type of non-dependent telescopes and `Tele` is the type of dependent telescopes.
</span><span class="comment-delimiter">-- </span><span class="comment">We can define a function that folds both kinds of telescopes into a functional type:
</span>
<span class="agda2-highlight-function">FoldBy</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-postulate">Level</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">TeleBy</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">αs</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr₁</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">_⊔_</span></span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">FoldBy</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">app</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span>
<span class="agda2-highlight-function">FoldBy</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">app</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">H</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">FoldBy</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">app</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">app</span> <span class="agda2-highlight-bound-variable">H</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">Two expected instances are
</span>
<span class="agda2-highlight-function">FoldSets</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr₁</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">_⊔_</span></span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">FoldSets</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">FoldBy</span> <span class="agda2-highlight-function">SetsF</span> <span class="agda2-highlight-function">const</span>
<span class="agda2-highlight-function">FoldTele</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldr₁</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">_⊔_</span></span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">FoldTele</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">FoldBy</span> <span class="agda2-highlight-function">TeleF</span> <span class="agda2-highlight-function">id</span>
<span class="comment-delimiter">-- </span><span class="comment">Examples:
</span>
<span class="agda2-highlight-function">ex-FoldSets</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">FoldSets</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">ex-FoldSets</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">ex-FoldTele</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">FoldTele</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set₁</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">ex-FoldTele</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">Using `FoldSets` we can define fully universe polymorphic arity-generic `mapⁿ`.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Mapⁿ</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Vec</span>
<span class="agda2-highlight-function">applyⁿ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">FoldSets</span> <span class="agda2-highlight-bound-variable">As</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">FoldSets</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">mapSets</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">flip</span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">As</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">applyⁿ</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">applyⁿ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">fs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">applyⁿ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">fs</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊛</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">mapⁿ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Sets</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">FoldSets</span> <span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">FoldSets</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">mapSets</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">flip</span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">As</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">mapⁿ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">applyⁿ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">replicate</span>
<span class="comment-delimiter">-- </span><span class="comment">`mapⁿ n f xs₁ xs₂ ... xsₙ` evaluates to `replicate f ⊛ xs₁ ⊛ xs₂ ⊛ ... ⊛ xsₙ`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">A test:
</span>
<span class="agda2-highlight-function">test-mapⁿ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">mapⁿ</span> <span class="agda2-highlight-number">2</span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-number">2</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-number">2</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-number">2</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Fin</span> <span class="agda2-highlight-number">2</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">test-mapⁿ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">In the rest of the post I'll translate the arity-generic machinery described at [1]
</span><span class="comment-delimiter">-- </span><span class="comment">to this setting. I won't describe it as it's already described there.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Comp</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">init</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">init</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">init</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-function">init</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⋯>ⁿ_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊔ⁿ</span></span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⋯>ⁿ_</span></span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⋯>ⁿ_</span></span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">F</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⋯>ⁿ</span></span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">Πⁿ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⋯>ⁿ</span></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊔ⁿ</span></span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Πⁿ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-symbol">_)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">Πⁿ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">_}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">F</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Πⁿ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">Comp</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⋯>ⁿ</span></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">FoldTele</span> <span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">init</span> <span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊔ⁿ</span></span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Comp</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">Comp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Comp</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">comp</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">αs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-postulate">Level</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">^</span></span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Tele</span> <span class="agda2-highlight-bound-variable">αs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⋯>ⁿ</span></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Πⁿ</span> <span class="agda2-highlight-bound-variable">As</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">FoldTele</span> <span class="agda2-highlight-bound-variable">As</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Comp</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">f</span>
<span class="agda2-highlight-function">comp</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span>
<span class="agda2-highlight-function">comp</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">comp</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">TestComp</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Bool.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Vec</span>
<span class="agda2-highlight-function">length</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">length</span> <span class="agda2-highlight-symbol">{</span>n <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">explicit-replicate</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">explicit-replicate</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">replicate</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">foo</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">foo</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">comp</span> <span class="agda2-highlight-number">3</span> <span class="agda2-highlight-function">length</span> <span class="agda2-highlight-function">explicit-replicate</span>
<span class="agda2-highlight-function">test-foo</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">foo</span> <span class="agda2-highlight-datatype">Bool</span> <span class="agda2-highlight-number">5</span> <span class="agda2-highlight-inductive-constructor">true</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-number">5</span>
<span class="agda2-highlight-function">test-foo</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
</pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0tag:blogger.com,1999:blog-5131816758284711343.post-76877541784997432292016-02-25T06:39:00.003-08:002016-02-25T06:39:30.580-08:00Normalization by Evaluation<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>NbE.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-postulate {
/* agda2-highlight-postulate-face */
color: #0000cd;
}
.agda2-highlight-primitive {
/* agda2-highlight-primitive-face */
color: #0000cd;
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
.comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="comment-delimiter">-- </span><span class="comment">Stealing an intro from sigfpe ([1]),
</span><span class="comment-delimiter">-- </span><span class="comment">I've decided that Normalization by Evaluation is the hardest trivial thing in type theory.
</span><span class="comment-delimiter">-- </span><span class="comment">Let's go down the rabbit hole.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">NbE</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Empty</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Sum</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Readback</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">3</span> ƛ_
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">6</span> _·_ _∙_
<span class="comment-delimiter">-- </span><span class="comment">NbE is usually explained like this:
</span> <span class="comment-delimiter">-- </span><span class="comment">1. first-order lambda terms representation
</span> <span class="comment-delimiter">-- </span><span class="comment">2. higher-order lambda terms representation
</span> <span class="comment-delimiter">-- </span><span class="comment">3. `readback'
</span> <span class="comment-delimiter">-- </span><span class="comment">4. `eval`
</span> <span class="comment-delimiter">-- </span><span class="comment">5. `norm = readback ∘ eval`
</span>
<span class="comment-delimiter">-- </span><span class="comment">Our plan is as follows:
</span> <span class="comment-delimiter">-- </span><span class="comment">1. higher-order lambda terms representation
</span> <span class="comment-delimiter">-- </span><span class="comment">2. normalization for higher-order lambda terms
</span> <span class="comment-delimiter">-- </span><span class="comment">3. first-order lambda terms representation
</span> <span class="comment-delimiter">-- </span><span class="comment">4. `toValue`, `fromValue`
</span> <span class="comment-delimiter">-- </span><span class="comment">5. `norm = fromValue ∘ normValue ∘ toValue`
</span> <span class="comment-delimiter">-- </span><span class="comment">6. `eval`
</span> <span class="comment-delimiter">-- </span><span class="comment">7. `norm = readback ∘ eval`
</span>
<span class="comment-delimiter">-- </span><span class="comment">The higher-order lambda terms representation is
</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NO_POSITIVITY_CHECK</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_·_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set₁</span>
<span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="comment-delimiter">-- </span><span class="comment">A few examples:
</span>
<span class="agda2-highlight-function">Iᵥ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">Iᵥ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">Kᵥ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">Kᵥ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">Sᵥ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">Sᵥ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">It might be instructive to add some parentheses:
</span>
<span class="agda2-highlight-function">S⁽⁾</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">S⁽⁾</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">))))</span>
<span class="comment-delimiter">-- </span><span class="comment">`lam` receives a continuation that returns a `Value`.
</span> <span class="comment-delimiter">-- </span><span class="comment">"Continuations are programs with holes in them" (quoted from [2]),
</span> <span class="comment-delimiter">-- </span><span class="comment">so `S` says "give me some `f`, `g` and `x`" and I'll produce `f · x · (g · x)` to you".
</span> <span class="comment-delimiter">-- </span><span class="comment">But these `f`, `g` and `x` are themselves `VTerm`s,
</span> <span class="comment-delimiter">-- </span><span class="comment">hence we can define function application that β-reduces:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∙_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span>
<span class="comment-delimiter">-- </span><span class="comment">If the head constructor is `lam`, then there is a hole that we can fill.
</span> <span class="comment-delimiter">-- </span><span class="comment">Otherwise we simply use the `_·_` constructor.
</span>
<span class="comment-delimiter">-- </span><span class="comment">A simple test:
</span>
<span class="agda2-highlight-function">SI</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Sᵥ</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-function">Iᵥ</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Iᵥ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">SI</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">`f` was substituted by `Iᵥ`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Normalization of a `Value` is similar:
</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">case</span></span> <span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">of</span></span> <span class="agda2-highlight-symbol">λ</span>
<span class="agda2-highlight-symbol">{</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">;</span> <span class="agda2-highlight-bound-variable">nf</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">nf</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-symbol">}</span>
<span class="comment-delimiter">-- </span><span class="comment">In the `f · x` case we first normalize `f`, if the head constructor is `lam`,
</span> <span class="comment-delimiter">-- </span><span class="comment">then there is a hole, we fill it and proceed further. Otherwise
</span> <span class="comment-delimiter">-- </span><span class="comment">`normValue (f · x)` is the same as `normValue f · normValue x`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">An example:
</span>
<span class="agda2-highlight-function">SKK</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Sᵥ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">Kᵥ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">Kᵥ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">Iᵥ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">SKK</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">The first-order representation of lambda terms will contain de Bruijn indices
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_·_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="comment-delimiter">-- </span><span class="comment">A few examples:
</span>
<span class="agda2-highlight-function">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">I</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function">K</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">K</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">1</span>
<span class="agda2-highlight-function">S</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">S</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">2</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is a function that converts higher-order lambda terms to theiry first-order counterparts:
</span>
<span class="agda2-highlight-function">var⁺</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">var⁺</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">∸</span></span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">∸</span></span> <span class="agda2-highlight-number">1</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">fromValue</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">fromValue</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">m</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">var⁺</span> <span class="agda2-highlight-bound-variable">m</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)))</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="comment-delimiter">-- </span><span class="comment">In `go` `n` represents the number of already encountered lambda abstractions.
</span> <span class="comment-delimiter">-- </span><span class="comment">On encountering a `lam`, we prepend a lambda to the resulting term and
</span> <span class="comment-delimiter">-- </span><span class="comment">apply the continuation to a fresh variable represented as a number of encountered
</span> <span class="comment-delimiter">-- </span><span class="comment">lambdas wrapped in `pure`. We also increase the lambdas counter.
</span> <span class="comment-delimiter">-- </span><span class="comment">In the `go n (pure m)` case we know that some variable was substituted by `pure m`,
</span> <span class="comment-delimiter">-- </span><span class="comment">where `m` was a number of encountered so far lambdas.
</span> <span class="comment-delimiter">-- </span><span class="comment">And now the number of encountered lambdas is `n`.
</span> <span class="comment-delimiter">-- </span><span class="comment">Thus, the resulting de Bruijn index is `n ∸ m ∸ 1`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Here are some reductions:
</span>
<span class="comment-delimiter">-- </span><span class="comment">`fromValue Iᵥ`
</span> <span class="comment-delimiter">-- </span><span class="comment">`go 0 (lam λ x -> x)`
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ (go 1 (pure 0))`
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var vz`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`fromValue Kᵥ`
</span> <span class="comment-delimiter">-- </span><span class="comment">`go 0 (lam λ x -> lam λ y -> x)`
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ (go 1 (lam λ y -> pure 0))`
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ ƛ (go 2 (pure 0))`
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ ƛ var 1`
</span>
<span class="agda2-highlight-function">Sᵥ≈S</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">fromValue</span> <span class="agda2-highlight-function">Sᵥ</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function">S</span>
<span class="agda2-highlight-function">Sᵥ≈S</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">We'll need some unsafe silliness in order to define the `toValue` function.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">_</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">postulate</span> <span class="agda2-highlight-postulate">undefined</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-postulate">undefined</span>
<span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">toValue</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">toValue</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">ρ</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">b</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="comment-delimiter">-- </span><span class="comment">In `go` `ρ` is an environment -- a list of already introduced bindings.
</span> <span class="comment-delimiter">-- </span><span class="comment">When encounter a `ƛ`, we prepend `lam` to the result, bind a variable
</span> <span class="comment-delimiter">-- </span><span class="comment">and add this binding to the environment. Later, in the `var n` case we take the nth binding.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Here are some reductions:
</span>
<span class="comment-delimiter">-- </span><span class="comment">`toValue I`
</span> <span class="comment-delimiter">-- </span><span class="comment">`go [] (ƛ var 0)`
</span> <span class="comment-delimiter">-- </span><span class="comment">`lam λ x -> go (x ∷ []) (var 0)`
</span> <span class="comment-delimiter">-- </span><span class="comment">`lam λ x -> x`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`toValue K`
</span> <span class="comment-delimiter">-- </span><span class="comment">`go [] (ƛ ƛ var 1)`
</span> <span class="comment-delimiter">-- </span><span class="comment">`lam λ x -> go (x ∷ []) (ƛ var 1)`
</span> <span class="comment-delimiter">-- </span><span class="comment">`lam λ x -> lam λ y -> go (y ∷ x ∷ []) (var 1)`
</span> <span class="comment-delimiter">-- </span><span class="comment">`lam λ x -> lam λ y -> x`
</span>
<span class="agda2-highlight-function">S≈Sᵥ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">toValue</span> <span class="agda2-highlight-function">S</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function">Sᵥ</span>
<span class="agda2-highlight-function">S≈Sᵥ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">Finally, the normalization function:
</span>
<span class="agda2-highlight-function">norm′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">norm′</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">fromValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">normValue</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">toValue</span> <span class="agda2-highlight-bound-variable">t</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">SKK≈I′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">norm′</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">S</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">K</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">K</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function">I</span>
<span class="agda2-highlight-function">SKK≈I′</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="comment-delimiter">-- </span><span class="comment">`norm` is usually defined in terms of `readback` (or `quote`) and `eval`.
</span> <span class="comment-delimiter">-- </span><span class="comment">`readback` is the same thing as `fromValue`
</span>
<span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">fromValue</span>
<span class="comment-delimiter">-- </span><span class="comment">and `eval` is like `normValue ∘ toValue`, but in one phase:
</span>
<span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">ρ</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">b</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="comment-delimiter">-- </span><span class="comment">The only difference between toValue` and `eval` is that function application
</span> <span class="comment-delimiter">-- </span><span class="comment">β-reduces in the latter case, i.e. it's `go ρ f ∙ go ρ x` instead of `go ρ f · go ρ x`.
</span>
<span class="agda2-highlight-function">norm</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">norm</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-function">eval</span>
<span class="agda2-highlight-function">SKK≈I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">norm</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">S</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">K</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-function">K</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function">I</span>
<span class="agda2-highlight-function">SKK≈I</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">S≈S</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">norm</span> <span class="agda2-highlight-function">S</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function">S</span>
<span class="agda2-highlight-function">S≈S</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">NewValues</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">Readback</span> <span class="agda2-highlight-keyword">using</span> <span class="agda2-highlight-symbol">(</span>Term<span class="agda2-highlight-symbol">;</span> var<span class="agda2-highlight-symbol">;</span> ƛ_<span class="agda2-highlight-symbol">;</span> _·_<span class="agda2-highlight-symbol">;</span> var⁺<span class="agda2-highlight-symbol">;</span> unsafeLookup<span class="agda2-highlight-symbol">;</span> I<span class="agda2-highlight-symbol">;</span> K<span class="agda2-highlight-symbol">;</span> S<span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-keyword">public</span>
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">6</span> _·⁺_ _∙_
<span class="comment-delimiter">-- </span><span class="comment">Our next step is to remove `_·_` from `Value`s and define normalization within this setting.
</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">NO_POSITIVITY_CHECK</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="comment-delimiter">-- </span><span class="comment">With the de Bruijn indices approach a variable can be denoted by different indices in a term,
</span> <span class="comment-delimiter">-- </span><span class="comment">depending on how many variables were introduced after it.
</span> <span class="comment-delimiter">-- </span><span class="comment">E.g. consider the `ω` combinator: `ƛ var 0 · var 0`. We can η-expand the last `var 0` and get
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var 0 · (ƛ var 1 · var 0)`. The variable introduced by the first lambda is denoted
</span> <span class="comment-delimiter">-- </span><span class="comment">first as `var 0` and then as `var 1`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">It's a problem, because we want to fill a hole in a term `lam λ x -> ...`
</span> <span class="comment-delimiter">-- </span><span class="comment">by passing something to the continuation, so `x` will everywhere be replaced by
</span> <span class="comment-delimiter">-- </span><span class="comment">some expression. But de Bruijn indices are context dependent, so it's not possible to
</span> <span class="comment-delimiter">-- </span><span class="comment">do that with them.
</span>
<span class="comment-delimiter">-- </span><span class="comment">There is no such problem with de Bruijn levels (e.g. the `S` combinator with
</span> <span class="comment-delimiter">-- </span><span class="comment">de Bruijn levels is represented as `ƛ ƛ ƛ var 0 · var 2 · (var 1 · var 2)`).
</span> <span class="comment-delimiter">-- </span><span class="comment">The `ω` combinator with de Bruijn levels is the same `ƛ var 0 · var 0`,
</span> <span class="comment-delimiter">-- </span><span class="comment">but if we now η-expand the last `var 0`, we'll get `ƛ var 0 · (ƛ var 0 · var 1)`.
</span> <span class="comment-delimiter">-- </span><span class="comment">The variable introduced by the first lambda is `var 0` everywhere.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The solution is to emulate de Bruijn levels using the liftable terms approach
</span> <span class="comment-delimiter">-- </span><span class="comment">(the terminology is due to [3]). Instead of instantiating `x` in `lam λ x -> ...` with
</span> <span class="comment-delimiter">-- </span><span class="comment">a term, we'll instantiate it with a function that returns a term. Lately, the function
</span> <span class="comment-delimiter">-- </span><span class="comment">will be applied to the number of encountered lambdas and will compute the term
</span> <span class="comment-delimiter">-- </span><span class="comment">accordingly to this context.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Liftable terms are
</span>
<span class="agda2-highlight-function">Term⁺</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Term⁺</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="comment-delimiter">-- </span><span class="comment">We have already seen liftable variables:
</span>
<span class="comment-delimiter">-- </span><span class="comment">var⁺ : ℕ -> ℕ -> Term
</span> <span class="comment-delimiter">-- </span><span class="comment">var⁺ m n = var (n ∸ m ∸ 1)
</span>
<span class="comment-delimiter">-- </span><span class="comment">Function application for liftable terms is straightforward:
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_·⁺_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Term⁺</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term⁺</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term⁺</span>
<span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">·⁺</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="comment-delimiter">-- </span><span class="comment">As promised terms in the model are
</span>
<span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-function">Term⁺</span>
<span class="comment-delimiter">-- </span><span class="comment">`readback` receives a `VTerm` and a number of already encountered lambdas.
</span>
<span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term⁺</span>
<span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">t</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">var⁺</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)))</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">))</span>
<span class="comment-delimiter">-- </span><span class="comment">On encountering `lam λ x -> ...` `x` gets instantiated to `pure (var⁺ n)` --
</span> <span class="comment-delimiter">-- </span><span class="comment">recall that `var⁺ n m` returns the de Bruijn index of a variable introduced by `n`th lambda
</span> <span class="comment-delimiter">-- </span><span class="comment">in a context with `m` lambdas. We also increase the lambdas counter by `suc n`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Function application for values is
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∙_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">·⁺</span></span> <span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="comment-delimiter">-- </span><span class="comment">The `lam` case is the same. `_∙_` is used such that in the `pure` case
</span> <span class="comment-delimiter">-- </span><span class="comment">`f` is always a neutral term and hence `x` can safely be readback -- it won't participate
</span> <span class="comment-delimiter">-- </span><span class="comment">in β-reductions. So this is how we construct terms: we collect function applications
</span> <span class="comment-delimiter">-- </span><span class="comment">under the `pure` wrapper.
</span>
<span class="comment-delimiter">-- </span><span class="comment">`eval` is the same as before.
</span>
<span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">ρ</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">b</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">norm</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">norm</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">readback</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-bound-variable">t</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-number">0</span>
<span class="comment-delimiter">-- </span><span class="comment">Let's now look at an example.
</span>
<span class="agda2-highlight-function">ηω</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">ηω</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">1</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">`norm ηω` reduces like this:
</span>
<span class="comment-delimiter">-- </span><span class="comment">expand all definitions:
</span> <span class="comment-delimiter">-- </span><span class="comment">`norm ηω`
</span> <span class="comment-delimiter">-- </span><span class="comment">`readback (eval ηω) 0`
</span> <span class="comment-delimiter">-- </span><span class="comment">`readback (lam λ x -> x ∙ (lam λ y -> x ∙ y)) 0`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`readback` consumes `lam`:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ readback (pure (var⁺ 0) ∙ (lam λ y -> pure (var⁺ 0) ∙ y)) 1`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`_∙_` fires:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ readback (pure (var⁺ 0 ·⁺ readback (lam λ y -> pure (var⁺ 0) ∙ y))) 1`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`readback` consumes `pure`:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ (var⁺ 0 ·⁺ readback (lam λ y -> pure (var⁺ 0) ∙ y)) 1`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`_·⁺_` fires:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var⁺ 0 1 · readback (lam λ y -> pure (var⁺ 0) ∙ y)) 1`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`var⁺ 0 1` reduces:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var 0 · readback (lam λ y -> pure (var⁺ 0) ∙ y)) 1`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`readback` consumes `lam`:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var 0 · (ƛ readback (pure (var⁺ 0) ∙ pure (var⁺ 1)) 2)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`_∙_` fires:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var 0 · (ƛ readback (pure (var⁺ 0 ·⁺ readback (pure (var⁺ 1)))) 2)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`readback`s consume `pure`s:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var 0 · (ƛ (var⁺ 0 ·⁺ var⁺ 1) 2)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`_·⁺_` fires
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var 0 · (ƛ var⁺ 0 2 · var⁺ 1 2)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">`var⁺` reduce:
</span> <span class="comment-delimiter">-- </span><span class="comment">`ƛ var 0 · (ƛ var 1 · var 0)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">and we're done.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The key point is that the number of encountered lambdas is traced over the whole computation.
</span> <span class="comment-delimiter">-- </span><span class="comment">`_·⁺_` "distributes" it, `var⁺` and `readback` consume it. `_∙_` "resumes" `readback`:
</span>
<span class="comment-delimiter">-- </span><span class="comment">`pure f ∙ x = pure (f ·⁺ readback x)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">and it always starts at the point where the previous `readback` stopped
</span> <span class="comment-delimiter">-- </span><span class="comment">(i.e. with the same amount of encountered lambdas), where "stopping" is
</span>
<span class="comment-delimiter">-- </span><span class="comment">`readback (pure t) n = t n`
</span>
<span class="comment-delimiter">-- </span><span class="comment">This also explains why we can't simply use de Bruijn levels -- it's anyway necessarily to
</span> <span class="comment-delimiter">-- </span><span class="comment">trace a number of encountered lambdas to be able to resume `readback`.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Reify&Reflect</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">NewValues</span> <span class="agda2-highlight-keyword">hiding</span> <span class="agda2-highlight-symbol">(</span>readback<span class="agda2-highlight-symbol">;</span> _∙_<span class="agda2-highlight-symbol">;</span> eval<span class="agda2-highlight-symbol">;</span> norm<span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">6</span> _⇒_
<span class="comment-delimiter">-- </span><span class="comment">There is another standard variant of Normalization by Evaluation:
</span> <span class="comment-delimiter">-- </span><span class="comment">in terms of `reify` and `reflect`. It's type-directed, so we'll need some types for it:
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">⋆</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⇒_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Type</span>
<span class="agda2-highlight-keyword">postulate</span> <span class="agda2-highlight-postulate">undefined</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span>
<span class="comment-delimiter">-- </span><span class="comment">Function application that β-reduces remains the same for the `lam` case
</span> <span class="comment-delimiter">-- </span><span class="comment">and becomes undefined otherwise.
</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_∙_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-postulate">undefined</span>
<span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="comment-delimiter">-- </span><span class="comment">`eval` is the same.
</span>
<span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Value</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">unsafeLookup</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">ρ</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">b</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∙</span></span> <span class="agda2-highlight-function">go</span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="comment-delimiter">-- </span><span class="comment">The core of the approach:
</span>
<span class="agda2-highlight-keyword">mutual</span>
<span class="agda2-highlight-function">reify</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term⁺</span>
<span class="agda2-highlight-function">reify</span> <span class="agda2-highlight-inductive-constructor">⋆</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">t</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">reify</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-bound-variable">k</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">reify</span> <span class="agda2-highlight-bound-variable">τ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">k</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">rvar⁺</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">))</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-function">reify</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-symbol">_</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-postulate">undefined</span>
<span class="agda2-highlight-function">reflect</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term⁺</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">reflect</span> <span class="agda2-highlight-inductive-constructor">⋆</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">t</span>
<span class="agda2-highlight-function">reflect</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">lam</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">reflect</span> <span class="agda2-highlight-bound-variable">τ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">·⁺</span></span> <span class="agda2-highlight-function">reify</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">rvar⁺</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">VTerm</span>
<span class="agda2-highlight-function">rvar⁺</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">reflect</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">var⁺</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">norm</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Term</span>
<span class="agda2-highlight-function">norm</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">reify</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-bound-variable">t</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-number">0</span>
<span class="comment-delimiter">-- </span><span class="comment">Compare `reify` to `readback`:
</span>
<span class="comment-delimiter">-- </span><span class="comment">readback : VTerm -> Term⁺
</span> <span class="comment-delimiter">-- </span><span class="comment">readback (pure t) n = t n
</span> <span class="comment-delimiter">-- </span><span class="comment">readback (lam k) n = ƛ (readback (k (pure (var⁺ n))) (suc n))
</span>
<span class="comment-delimiter">-- </span><span class="comment">They are very similar except that in `readback` `k` receives `pure (var⁺ n)`
</span> <span class="comment-delimiter">-- </span><span class="comment">and in `reify` `k` receives `reflect σ (var⁺ n)` (after unfolding `rvar⁺ σ n`).
</span> <span class="comment-delimiter">-- </span><span class="comment">`reify` is also type-directed, hence it performs full η-expansion.
</span>
<span class="comment-delimiter">-- </span><span class="comment">So what's the difference between `pure (var⁺ n)` and `reflect σ (var⁺ n)`?
</span> <span class="comment-delimiter">-- </span><span class="comment">`reflect` performs η-expansion of values.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Recall how `_∙_` was defined in the previous section:
</span>
<span class="comment-delimiter">-- </span><span class="comment">_∙_ : VTerm -> VTerm -> VTerm
</span> <span class="comment-delimiter">-- </span><span class="comment">pure f ∙ x = pure (f ·⁺ readback x)
</span> <span class="comment-delimiter">-- </span><span class="comment">lam k ∙ x = k x
</span>
<span class="comment-delimiter">-- </span><span class="comment">With this definition `pure (var⁺ n) ∙ x` reduces to `pure (var⁺ n ·⁺ readback x)`.
</span> <span class="comment-delimiter">-- </span><span class="comment">`reflect` allows to reduce the expression in the same way while leaving `_∙_` undefined
</span> <span class="comment-delimiter">-- </span><span class="comment">in the `pure` case. Instead, both the tasks of performing β-reductions and collecting
</span> <span class="comment-delimiter">-- </span><span class="comment">function applications under the `pure` wrapper we solve using just `lam`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Consider `rvar⁺ (⋆ ⇒ ⋆) n ∙ x`. It reduces to `(lam λ y -> pure (var⁺ n ·⁺ reify σ y)) ∙ x`
</span> <span class="comment-delimiter">-- </span><span class="comment">and further to `pure (var⁺ n ·⁺ reify σ x)`. Just the same expression as before
</span> <span class="comment-delimiter">-- </span><span class="comment">(keep in mind that `reify` is a new version of `readback`).
</span>
<span class="comment-delimiter">-- </span><span class="comment">That's basically it. The `reify&reflect` approach is just the `readback` approach
</span> <span class="comment-delimiter">-- </span><span class="comment">after some reshuffling.
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Typed</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">The next step is to define normalization for Church-like typed terms.
</span> <span class="comment-delimiter">-- </span><span class="comment">It's straightforward to adapt the liftable terms approach to typed setting
</span> <span class="comment-delimiter">-- </span><span class="comment">(though, it still costs a `postulate`). An implementation can be found here:
</span>
<span class="comment-delimiter">-- </span><span class="comment">https://github.com/effectfully/random-stuff/blob/master/Normalization/Liftable.agda
</span>
<span class="comment-delimiter">-- </span><span class="comment">Note that this approach allows to get a first-order representation
</span> <span class="comment-delimiter">-- </span><span class="comment">of a pure Agda lambda term, see the examples at the end of the file.
</span>
<span class="comment-delimiter">-- </span><span class="comment">The implementation is in terms of `reify` and `reflect`. It's adapted from [4].
</span>
<span class="comment-delimiter">-- </span><span class="comment">But the actual magic happens when you interpret function space of the target language
</span> <span class="comment-delimiter">-- </span><span class="comment">in a Kripke-like fashion and thus incorporate weakening into semantics.
</span> <span class="comment-delimiter">-- </span><span class="comment">I'm not very comfortable with this approach, so I won't describe it either, but
</span> <span class="comment-delimiter">-- </span><span class="comment">a minimal implementation (in terms of `readback`) can be found here:
</span>
<span class="comment-delimiter">-- </span><span class="comment">https://github.com/effectfully/random-stuff/blob/master/Normalization/Readback.agda
</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">References</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">[1] "Reverse Engineering Machines with the Yoneda Lemma"
</span> <span class="comment-delimiter">-- </span><span class="comment">Dan Piponi
</span> <span class="comment-delimiter">-- </span><span class="comment">http://blog.sigfpe.com/2006/11/yoneda-lemma.html
</span>
<span class="comment-delimiter">-- </span><span class="comment">[2] http://stackoverflow.com/a/32146054/3237465
</span>
<span class="comment-delimiter">-- </span><span class="comment">[3] "Normalization by Evaluation for Martin-Löf Type Theory with One Universe"
</span> <span class="comment-delimiter">-- </span><span class="comment">Andreas Abel, Klaus Aehlig, Peter Dybjer
</span> <span class="comment-delimiter">-- </span><span class="comment">http://www.cse.chalmers.se/~peterd/papers/NbeMLTT.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[4] "Normalization by Evaluation, Dependent Types and Impredicativity"
</span> <span class="comment-delimiter">-- </span><span class="comment">Andreas Abel
</span> <span class="comment-delimiter">-- </span><span class="comment">http://www.cse.chalmers.se/~abela/habil.pdf
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0tag:blogger.com,1999:blog-5131816758284711343.post-44441439987836800382016-02-20T07:43:00.001-08:002016-02-20T07:43:07.950-08:00Simple generic programming.<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<!-- Created by htmlize-1.43 in css mode. -->
<html>
<head>
<title>Rose.agda</title>
<style type="text/css">
<!--
body {
color: SystemWindowText;
background-color: SystemWindow;
}
.agda2-highlight-bound-variable {
}
.agda2-highlight-datatype {
/* agda2-highlight-datatype-face */
color: #0000cd;
}
.agda2-highlight-field {
/* agda2-highlight-field-face */
color: #ee1289;
}
.agda2-highlight-function {
/* agda2-highlight-function-face */
color: #0000cd;
}
.agda2-highlight-inductive-constructor {
/* agda2-highlight-inductive-constructor-face */
color: #008b00;
}
.agda2-highlight-keyword {
/* agda2-highlight-keyword-face */
color: #cd6600;
}
.agda2-highlight-module {
/* agda2-highlight-module-face */
color: #a020f0;
}
.agda2-highlight-number {
/* agda2-highlight-number-face */
color: #a020f0;
}
.agda2-highlight-operator {
}
.agda2-highlight-primitive {
/* agda2-highlight-primitive-face */
color: #0000cd;
}
.agda2-highlight-primitive-type {
/* agda2-highlight-primitive-type-face */
color: #0000cd;
}
.agda2-highlight-record {
/* agda2-highlight-record-face */
color: #0000cd;
}
.agda2-highlight-symbol {
/* agda2-highlight-symbol-face */
color: #404040;
}
.comment {
/* font-lock-comment-face */
color: #b22222;
}
.comment-delimiter {
/* font-lock-comment-delimiter-face */
color: #b22222;
}
a {
color: inherit;
background-color: inherit;
font: inherit;
text-decoration: inherit;
}
a:hover {
text-decoration: underline;
}
-->
</style>
</head>
<body>
<pre>
<span class="comment-delimiter">-- </span><span class="comment">When I was reading about descriptions ([1]), I was wondering whether
</span><span class="comment-delimiter">-- </span><span class="comment">there is an encoding that is not that powerful, but simple, straightforward
</span><span class="comment-delimiter">-- </span><span class="comment">and allows to encode a vast amount of data types among with their elimination principles
</span><span class="comment-delimiter">-- </span><span class="comment">(the containers approach ([2]) doesn't allow this in an intensional type theory [3]).
</span><span class="comment-delimiter">-- </span><span class="comment">I'll describe such encoding.
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Level</span> <span class="agda2-highlight-keyword">renaming</span> <span class="agda2-highlight-symbol">(</span>zero <span class="agda2-highlight-symbol">to</span> lzero<span class="agda2-highlight-symbol">;</span> suc <span class="agda2-highlight-symbol">to</span> lsuc<span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Function</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Relation.Binary.PropositionalEquality</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Nat.Base</span> <span class="agda2-highlight-keyword">renaming</span> <span class="agda2-highlight-symbol">(</span>_⊔_ <span class="agda2-highlight-symbol">to</span> _⊔ℕ_<span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.Product</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-keyword">import</span> <span class="agda2-highlight-module">Data.List.Base</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">5</span> _∷₁_
<span class="comment-delimiter">-- </span><span class="comment">`List₁ B xs` contains a `B x` for each `x` in `xs`.
</span><span class="comment-delimiter">-- </span><span class="comment">It's the same `All` from `Data.List.All`, but lies in `Set β` rather than `Set (α ⊔ β)`.
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">[]₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷₁_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">And here is the encoding.
</span>
<span class="agda2-highlight-function">Over</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ι</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">⊔</span></span> <span class="agda2-highlight-primitive">lsuc</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Over</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span>
<span class="agda2-highlight-keyword">record</span> <span class="agda2-highlight-record">Rose</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ι</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Over</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-primitive"><span class="agda2-highlight-operator">⊔</span></span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">inductive</span>
<span class="agda2-highlight-keyword">constructor</span> <span class="agda2-highlight-inductive-constructor">node</span>
<span class="agda2-highlight-keyword">field</span>
<span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-field">is</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">I</span>
<span class="agda2-highlight-field">cons</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">is</span> <span class="agda2-highlight-bound-variable">j</span>
<span class="agda2-highlight-field">childs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-record">Rose</span> <span class="agda2-highlight-bound-variable">F</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">is</span>
<span class="comment-delimiter">-- </span><span class="comment">`Over` describes all possible constructors of a data type and
</span><span class="comment-delimiter">-- </span><span class="comment">`Rose` ties the knot and connects these constructors together.
</span>
<span class="comment-delimiter">-- </span><span class="comment">`Rose` is able to express inductive families and that's why there is the `I` --
</span><span class="comment-delimiter">-- </span><span class="comment">it's the type of the indices of a data type.
</span>
<span class="comment-delimiter">-- </span><span class="comment">`Over` contains all information about a data type being described
</span><span class="comment-delimiter">-- </span><span class="comment">except for inductive occurrences, which are reflected to the type level
</span><span class="comment-delimiter">-- </span><span class="comment">by storing their indices in `List I`. The final `I` in
</span>
<span class="comment-delimiter">-- </span><span class="comment">Over I α = List I -> I -> Set α
</span>
<span class="comment-delimiter">-- </span><span class="comment">is for the index that a constructor produces.
</span>
<span class="comment-delimiter">-- </span><span class="comment">Here is how it looks for vectors:
</span><span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">Vec</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">VecF</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Over</span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">The first constructor for `Vec` (`[]ᵥ`) doesn't contain any data
</span> <span class="comment-delimiter">-- </span><span class="comment">and it produces the index `0`.
</span> <span class="agda2-highlight-inductive-constructor">Nil</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">VecF</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-number">0</span>
<span class="comment-delimiter">-- </span><span class="comment">The second constructor for `Vec` (`_∷ᵥ_`) contains an `A` and
</span> <span class="comment-delimiter">-- </span><span class="comment">an inductive occurrence of `Vec`. It produces the index `suc n`
</span> <span class="comment-delimiter">-- </span><span class="comment">where `n` is the index of the inductive occurrence.
</span> <span class="comment-delimiter">-- </span><span class="comment">Hence we put `n` into the list of indices of inductive occurrences and return `suc n`.
</span> <span class="agda2-highlight-inductive-constructor">Cons</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">VecF</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">`Vec` then is
</span>
<span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span>
<span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Rose</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">VecF</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="comment-delimiter">-- </span><span class="comment">Let's look again at the definition of `Rose`:
</span>
<span class="comment-delimiter">-- </span><span class="comment">record Rose {ι α} {I : Set ι} (F : Over I α) j : Set (ι ⊔ α) where
</span> <span class="comment-delimiter">-- </span><span class="comment">inductive
</span> <span class="comment-delimiter">-- </span><span class="comment">constructor node
</span> <span class="comment-delimiter">-- </span><span class="comment">field
</span> <span class="comment-delimiter">-- </span><span class="comment">{is} : List I
</span> <span class="comment-delimiter">-- </span><span class="comment">cons : F is j
</span> <span class="comment-delimiter">-- </span><span class="comment">childs : List₁ (Rose F) is
</span>
<span class="comment-delimiter">-- </span><span class="comment">`j` is an index of an inhabitant of a data type.
</span> <span class="comment-delimiter">-- </span><span class="comment">`is` is a list of indices of inductive occurrences.
</span> <span class="comment-delimiter">-- </span><span class="comment">`cons` is a constructor of this data type.
</span> <span class="comment-delimiter">-- </span><span class="comment">`childs` is a list of `Rose F i` for each `i` in `is`,
</span> <span class="comment-delimiter">-- </span><span class="comment">i.e. a list that actually contains inductive occurrences (finally).
</span>
<span class="comment-delimiter">-- </span><span class="comment">Recall the definition of `Cons`:
</span>
<span class="comment-delimiter">-- </span><span class="comment">`Cons : ∀ {n} -> A -> VecF A (n ∷ []) (suc n)`
</span>
<span class="comment-delimiter">-- </span><span class="comment">When we write `node (Cons x)` `is` gets unified with `_n ∷ []` and
</span> <span class="comment-delimiter">-- </span><span class="comment">`j` gets unified with `suc _n` for a fresh meta `_n`.
</span> <span class="comment-delimiter">-- </span><span class="comment">Thus, `childs` has type `List₁ (Vec A) (_n ∷ [])`,
</span> <span class="comment-delimiter">-- </span><span class="comment">i.e. there is exactly one child -- `Vec A n`.
</span>
<span class="comment-delimiter">-- </span><span class="comment">So here are the constructors:
</span>
<span class="comment-delimiter">-- </span><span class="comment">[]ᵥ : ∀ {α} {A : Set α} -> Vec A 0
</span> <span class="comment-delimiter">-- </span><span class="comment">[]ᵥ = node Nil []₁
</span>
<span class="comment-delimiter">-- </span><span class="comment">_∷ᵥ_ : ∀ {n α} {A : Set α} -> A -> Vec A n -> Vec A (suc n)
</span> <span class="comment-delimiter">-- </span><span class="comment">x ∷ᵥ xs = node (Cons x) (xs ∷₁ []₁)
</span>
<span class="comment-delimiter">-- </span><span class="comment">But for convenience we'll define them as pattern synonyms instead
</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">[]ᵥ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">Nil</span> <span class="agda2-highlight-inductive-constructor">[]₁</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷ᵥ_</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Cons</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-inductive-constructor">[]₁</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">And guess what, we have literally the same eliminator as for the usual `Vec`:
</span>
<span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-inductive-constructor">[]ᵥ</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-inductive-constructor">[]ᵥ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">z</span>
<span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">elimVec</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">So we basically don't need it -- we can use pattern matching directly, e.g.:
</span>
<span class="agda2-highlight-function">vmap</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">vmap</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor">[]ᵥ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]ᵥ</span>
<span class="agda2-highlight-function">vmap</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-function">vmap</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">vhead</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">A</span>
<span class="agda2-highlight-function">vhead</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">AnEliminator</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">We can of course define an eliminator of `Rose`.
</span> <span class="comment-delimiter">-- </span><span class="comment">But let's define an eliminator for something simpler first.
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Tree</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">branch</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Tree</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Tree</span> <span class="agda2-highlight-bound-variable">A</span>
<span class="comment-delimiter">-- </span><span class="comment">An eliminator is an induction principle and an induction hypothesis
</span> <span class="comment-delimiter">-- </span><span class="comment">sounds like "`P` holds, if it holds at every inductive position".
</span> <span class="comment-delimiter">-- </span><span class="comment">To say "`P` holds for a list `xs` of inductive occurrences" we write `List₁ P xs`.
</span> <span class="comment-delimiter">-- </span><span class="comment">Here is the eliminator:
</span>
<span class="agda2-highlight-function">elimTree</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Tree</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ts</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">ts</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">branch</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">ts</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">t</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">t</span>
<span class="agda2-highlight-function">elimTree</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">branch</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">ts</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">elimTrees</span> <span class="agda2-highlight-bound-variable">ts</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">elimTrees</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-bound-variable">ts</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">ts</span>
<span class="agda2-highlight-function">elimTrees</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]₁</span>
<span class="agda2-highlight-function">elimTrees</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-bound-variable">ts</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimTree</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-function">elimTrees</span> <span class="agda2-highlight-bound-variable">ts</span>
<span class="comment-delimiter">-- </span><span class="comment">`Rose` is basically the same thing as `Tree`, but there is `List₁` instead of `List`.
</span> <span class="comment-delimiter">-- </span><span class="comment">All we need is to define `List₂` over `List₁` in the same manner as `List₁` over `List` before.
</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">List₂</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">[]₂</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-inductive-constructor">[]₁</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_∷₂_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ys</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">ys</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">lmap₂</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">y</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">ys</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₂</span> <span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-bound-variable">ys</span>
<span class="agda2-highlight-function">lmap₂</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-inductive-constructor">[]₁</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]₂</span>
<span class="agda2-highlight-function">lmap₂</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₂</span></span> <span class="agda2-highlight-function">lmap₂</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">ys</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-function">elimRose</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ι</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Over</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Rose</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">is</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-bound-variable">cs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">is</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₂</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">cs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">cs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">r</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-record">Rose</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">r</span>
<span class="agda2-highlight-function">elimRose</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">cs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">lmap₂</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">elimRose</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">cs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">We could get rid of the `{-# TERMINATING #-}` pragma by inlining `lmap₂' and
</span> <span class="comment-delimiter">-- </span><span class="comment">defining `elimRose` mutually with `elimRoses` as in the case of `Tree`, but I hate this.
</span>
<span class="comment-delimiter">-- </span><span class="comment">As an example, let's define an eliminator for `Vec` in terms of `elimRose`.
</span>
<span class="agda2-highlight-keyword">open</span> <span class="agda2-highlight-module">Vec</span>
<span class="agda2-highlight-function">elimVec′</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">))</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-inductive-constructor">[]ᵥ</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="agda2-highlight-function">elimVec′</span> <span class="agda2-highlight-symbol">{</span>A <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">A</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">z</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">elimRose</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-function">h</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-function">h</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">is</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-bound-variable">cs</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">VecF</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">is</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₂</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-bound-variable">cs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">cs</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">h</span> <span class="agda2-highlight-inductive-constructor">Nil</span> <span class="agda2-highlight-inductive-constructor">[]₂</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">z</span>
<span class="agda2-highlight-function">h</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Cons</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₂</span></span> <span class="agda2-highlight-inductive-constructor">[]₂</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">xs</span>
<span class="comment-delimiter">-- </span><span class="comment">Not super nice, but works.
</span>
<span class="comment-delimiter">-- </span><span class="comment">A recursor is similar:
</span>
<span class="agda2-highlight-function">unmap₁</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">β</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">β</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">C</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">C</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List₁</span> <span class="agda2-highlight-bound-variable">B</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">C</span>
<span class="agda2-highlight-function">unmap₁</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-inductive-constructor">[]₁</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">[]</span>
<span class="agda2-highlight-function">unmap₁</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-bound-variable">ys</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">y</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-function">unmap₁</span> <span class="agda2-highlight-bound-variable">g</span> <span class="agda2-highlight-bound-variable">ys</span>
<span class="agda2-highlight-symbol">{-#</span> <span class="agda2-highlight-keyword">TERMINATING</span> <span class="agda2-highlight-symbol">#-}</span>
<span class="agda2-highlight-function">foldRose</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-bound-variable">α</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ι</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Over</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">π</span><span class="agda2-highlight-symbol">}</span>
<span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">is</span> <span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">is</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">List</span> <span class="agda2-highlight-bound-variable">P</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Rose</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">P</span>
<span class="agda2-highlight-function">foldRose</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-bound-variable">cs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">c</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">unmap₁</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">foldRose</span> <span class="agda2-highlight-bound-variable">f</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-bound-variable">cs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">We can define a generic `depth` function that returns the depth of any `Rose`.
</span>
<span class="agda2-highlight-function">depth</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">ι</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">ι</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Over</span> <span class="agda2-highlight-bound-variable">I</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">j</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-record">Rose</span> <span class="agda2-highlight-bound-variable">F</span> <span class="agda2-highlight-bound-variable">j</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function">depth</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">foldRose</span> <span class="agda2-highlight-symbol">(λ</span> <span class="agda2-highlight-bound-variable">_</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">foldr</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊔ℕ_</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">∘</span></span> <span class="agda2-highlight-inductive-constructor">suc</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-number">0</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">A simple test:
</span>
<span class="agda2-highlight-function">vec-depth</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-bound-variable">α</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Vec</span> <span class="agda2-highlight-bound-variable">A</span> <span class="agda2-highlight-bound-variable">n</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">depth</span> <span class="agda2-highlight-bound-variable">xs</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-bound-variable">n</span>
<span class="agda2-highlight-function">vec-depth</span> <span class="agda2-highlight-inductive-constructor">[]ᵥ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-function">vec-depth</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷ᵥ</span></span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">cong</span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">vec-depth</span> <span class="agda2-highlight-bound-variable">xs</span><span class="agda2-highlight-symbol">)</span>
<span class="comment-delimiter">-- </span><span class="comment">One restriction is that we can't describe data types in which an inductive position occurs
</span><span class="comment-delimiter">-- </span><span class="comment">to the right of the arrow in a parameter of a constructor (like e.g. in `W`).
</span><span class="comment-delimiter">-- </span><span class="comment">This is fixable: I wrote a library that deals with Observational Type Theory,
</span><span class="comment-delimiter">-- </span><span class="comment">`W` is expressible there and has the usual induction principle.
</span><span class="comment-delimiter">-- </span><span class="comment">Here it is: https://github.com/effectfully/OTT/blob/master/Data/W.agda
</span>
<span class="comment-delimiter">-- </span><span class="comment">An extended example: simply typed lambda calculus.
</span><span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">STLC</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">6</span> _⇒_
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">5</span> _▻_
<span class="agda2-highlight-keyword">infix</span> <span class="agda2-highlight-number">3</span> _∈_ _⊢_
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">4</span> vs_
<span class="agda2-highlight-keyword">infixr</span> <span class="agda2-highlight-number">0</span> ƛ_
<span class="agda2-highlight-keyword">infixl</span> <span class="agda2-highlight-number">6</span> _·_
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">nat</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_⇒_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Type</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">nat</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-datatype">ℕ</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">τ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">τ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">ε</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Con</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_▻_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Con</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">_∈_</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">vz</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▻</span></span> <span class="agda2-highlight-bound-variable">σ</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">vs_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▻</span></span> <span class="agda2-highlight-bound-variable">τ</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">Env</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">∅</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Env</span> <span class="agda2-highlight-inductive-constructor">ε</span>
<span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_▷_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Env</span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Env</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▻</span></span> <span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">lookupᵉ</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Env</span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span>
<span class="agda2-highlight-function">lookupᵉ</span> <span class="agda2-highlight-inductive-constructor">vz</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function">lookupᵉ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">vs</span></span> <span class="agda2-highlight-bound-variable">v</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">lookupᵉ</span> <span class="agda2-highlight-bound-variable">v</span> <span class="agda2-highlight-bound-variable">ρ</span>
<span class="agda2-highlight-keyword">data</span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-function">Over</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">×</span></span> <span class="agda2-highlight-datatype">Type</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-primitive">lzero</span> <span class="agda2-highlight-keyword">where</span>
<span class="agda2-highlight-inductive-constructor">Pure</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">Var</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">∈</span></span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">Lam</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▻</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">App</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">τ</span> <span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">Z</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-inductive-constructor">[]</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">nat</span> <span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">S</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">nat</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">nat</span> <span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-inductive-constructor">Fold</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-inductive-constructor">nat</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷</span></span> <span class="agda2-highlight-inductive-constructor">[]</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">_⊢_</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Con</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊢</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-record">Rose</span> <span class="agda2-highlight-datatype">TermF</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">,</span></span> <span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">Term⁺</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Term⁺</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊢</span></span> <span class="agda2-highlight-bound-variable">σ</span>
<span class="agda2-highlight-function">Term⁽⁾</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-datatype">Type</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-primitive-type">Set</span>
<span class="agda2-highlight-function">Term⁽⁾</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">ε</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊢</span></span> <span class="agda2-highlight-bound-variable">σ</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Pure</span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">[]₁</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">v</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor">Var</span> <span class="agda2-highlight-bound-variable">v</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor">[]₁</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ_</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">Lam</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-inductive-constructor">[]₁</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">_·_</span></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">App</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-inductive-constructor">[]₁</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">z</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">Z</span> <span class="agda2-highlight-inductive-constructor">[]₁</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">s</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">S</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-inductive-constructor">[]₁</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-keyword">pattern</span> <span class="agda2-highlight-inductive-constructor">tfold</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">node</span> <span class="agda2-highlight-inductive-constructor">Fold</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">∷₁</span></span> <span class="agda2-highlight-inductive-constructor">[]₁</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦_⟧ᵥ</span></span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⊢</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-datatype">Env</span> <span class="agda2-highlight-bound-variable">Γ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">pure</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-bound-variable">x</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-bound-variable">v</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">lookupᵉ</span> <span class="agda2-highlight-bound-variable">v</span> <span class="agda2-highlight-bound-variable">ρ</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-symbol">λ</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">b</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">▷</span></span> <span class="agda2-highlight-bound-variable">x</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">z</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-number">0</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">s</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">suc</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-inductive-constructor">tfold</span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function">fold</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">x</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">f</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">n</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-bound-variable">ρ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term⁽⁾</span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧</span></span>
<span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟦</span></span> <span class="agda2-highlight-bound-variable">t</span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">⟧ᵥ</span></span> <span class="agda2-highlight-inductive-constructor">∅</span>
<span class="agda2-highlight-function">A</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">Term⁺</span> <span class="agda2-highlight-symbol">((</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">⇒</span></span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">)</span>
<span class="agda2-highlight-function">A</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">ƛ</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">vs</span></span> <span class="agda2-highlight-inductive-constructor">vz</span><span class="agda2-highlight-symbol">)</span> <span class="agda2-highlight-inductive-constructor"><span class="agda2-highlight-operator">·</span></span> <span class="agda2-highlight-inductive-constructor">var</span> <span class="agda2-highlight-inductive-constructor">vz</span>
<span class="agda2-highlight-function">test</span> <span class="agda2-highlight-symbol">:</span> <span class="agda2-highlight-symbol">∀</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">σ</span> <span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">-></span> <span class="agda2-highlight-function">eval</span> <span class="agda2-highlight-symbol">(</span><span class="agda2-highlight-function">A</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">σ</span><span class="agda2-highlight-symbol">}</span> <span class="agda2-highlight-symbol">{</span><span class="agda2-highlight-bound-variable">τ</span><span class="agda2-highlight-symbol">})</span> <span class="agda2-highlight-datatype"><span class="agda2-highlight-operator">≡</span></span> <span class="agda2-highlight-function"><span class="agda2-highlight-operator">_$_</span></span>
<span class="agda2-highlight-function">test</span> <span class="agda2-highlight-symbol">=</span> <span class="agda2-highlight-inductive-constructor">refl</span>
<span class="agda2-highlight-keyword">module</span> <span class="agda2-highlight-module">References</span> <span class="agda2-highlight-keyword">where</span>
<span class="comment-delimiter">-- </span><span class="comment">[1] "The Gentle Art of Levitation"
</span> <span class="comment-delimiter">-- </span><span class="comment">James Chapman, Pierre-Evariste Dagand, Conor McBride, Peter Morris
</span> <span class="comment-delimiter">-- </span><span class="comment">http://jmchapman.github.io/papers/levitation.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[2] "Indexed Containers"
</span> <span class="comment-delimiter">-- </span><span class="comment">Thorsten Altenkirch, Neil Ghani, Peter Hancock, Conor McBride, Peter Morris
</span> <span class="comment-delimiter">-- </span><span class="comment">http://www.cs.nott.ac.uk/~psztxa/publ/jcont.pdf
</span>
<span class="comment-delimiter">-- </span><span class="comment">[3] "W-types: good news and bad news"
</span> <span class="comment-delimiter">-- </span><span class="comment">Conor McBride
</span> <span class="comment-delimiter">-- </span><span class="comment">http://mazzo.li/epilogue/index.html%3Fp=324.html
</span></pre>
</body>
</html>
effectfullyhttp://www.blogger.com/profile/03652893609060923856noreply@blogger.com0