続くといいな日記https://mizunashi-mana.github.io/blog/2023-12-06T11:53:49+09:00続くといいな日記Firefish のインストール方法2023-12-06T11:53:49+09:002023-12-06T11:53:49+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-12-06:/blog/posts/2023/12/install-firefish-by-deb/<p>Fediverse は ActivityPub により接続されたサーバ群によるネットワークである。ActivityPub は短文投稿、画像・動画共有、ファイル共有などを可 …</p><p>Fediverse は ActivityPub により接続されたサーバ群によるネットワークである。ActivityPub は短文投稿、画像・動画共有、ファイル共有などを可能とする、HTTP 上でコンテンツ共有・発信を可能とするソーシャルネットワークプロトコルだ。W3C 勧告であることもあって今や多くの実装が存在しサーバも世界中に多数立っている。</p>
<p>さて今回はその中で、Firefish という実装についての紹介と、自分で作っている Debian 向けの Firefish パッケージの導入方法について宣伝も兼ねて説明していく。なお、これは現時点での話で、Fediverse はかなり栄枯盛衰が激しいので、1年後には役に立たなくなってるかもしれない。ま、あくまで参考程度にしてくれって感じ。</p>
<p>なお、この記事は</p>
<ul class="simple">
<li><a class="reference external" href="https://adventar.org/calendars/8812">Fediverse (4) Advent Calendar 2023</a></li>
<li><a class="reference external" href="https://firefish.bloggy.naskya.net/">Firefish Advent Calendar 2023</a></li>
</ul>
<p>の6日目掲載記事となる。他の記事も Fediverse に関しての生の体験満載となっていて、色々面白いと思うので、ぜひ覗いてみて欲しい。</p>
<div class="section" id="auto-id-1">
<h2>他の実装との比較<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ActivityPub 対応のサーバは結構最近多いが、僕の周りで主流なのは以下:</p>
<dl class="docutils">
<dt>Mastodon: <a class="reference external" href="https://joinmastodon.org/">https://joinmastodon.org/</a></dt>
<dd>定番サーバ。AGPLv3 の OSS。サーバサイドはメインは Rails、ストリームサーバだけ Node.js 上で Express で書かれてる。Web クライアント側は React で書かれてる。クライアント側の事実上の API 標準になっているぐらいには、利用率が高い気がする。結構思想が強めで、分散 SNS の急先鋒という感じ。良くも悪くも機能のバランスは良く、安定性も高い印象はある。</dd>
<dt>Misskey: <a class="reference external" href="https://misskey-hub.net/">https://misskey-hub.net/</a></dt>
<dd>もう一つの定番サーバ。AGPLv3 の OSS。サーバサイドは Nest.js、Web クライアントは Vue で書かれてる。思想より、結構機能重視みたいなところがあり、いろいろ面白い機能を試しては載せていってるところに、マストドンなどにはない面白さを感じてるユーザが多そうだ。ただ、開発コミュニティが結構日本寄りということがあって、海外での利用率は低め。また、安定性も少し落ちる印象がある。それから、Mastodon API との互換がないため Mastodon 用アプリが使えなく、また Misskey 用のアプリもあまりないという面もあり、Web UI を利用してるユーザが多い。</dd>
<dt>Pleroma: <a class="reference external" href="https://docs-develop.pleroma.social/">https://docs-develop.pleroma.social/</a></dt>
<dd>個人サーバ立てる時人気のサーバ。AGPLv3 の OSS で、サーバサイドは Phoenix、Web クライアントは Vue で書かれてる。他のサーバに比べて軽いというのと、Web クライアントとサーバサイド実装が完全に分かれており、クライアント実装もいくつかあってカスタマイズしやすいこと、Mastodon API とある程度互換がありアプリが流用しやすいことが特徴的。ただ、大型サーバではあまり用いられてるのを見ない気がする。</dd>
<dt>Akkoma: <a class="reference external" href="https://akkoma.social/">https://akkoma.social/</a></dt>
<dd>Pleroma のフォーク。あまりよく知らないが、時折使ってる人はいそう。Pleroma にない機能が載ってたり、逆に Pleroma にはあるけど Akkoma にはない機能もあったりするみたいな噂。</dd>
<dt>Firefish: <a class="reference external" href="https://joinfirefish.org/">https://joinfirefish.org/</a></dt>
<dd>Misskey のフォークで、AGPLv3 の OSS。フォーク当時は Calckey という名前だったが、改名された。今回紹介するソフトウェアで、僕の個人鯖で使っている。</dd>
</dl>
<p>なお、これらは主に短文投稿 SNS 用途という感じだが、他に WordPress のプラグイン経由での発信、PeerTube、Lemmy などの短文投稿以外に特化したソフトウェアなどもある程度シェアを占めているようだ。</p>
<p>これらの中で Firefish の立ち位置は、Mastodon と Misskey の中間のような感じで、Misskey の便利な機能を取り入れつつ、Mastodon API も搭載していて Mastodon 用のクライアントアプリを使える <a class="footnote-reference" href="#support-status-mastodon-api-of-firefish" id="auto-id-2">[1]</a> のが特徴という感じになる。個人的に重宝してるのは、Web UI の見やすさとカスタム絵文字だろうか。UI でいうと、具体的には分散 SNS らしく発信元のソフトウェア情報が簡単に確認できるため、相手がどういう機能に対応してるソフトを使ってるか反応する前に予測できたり、設定から好みに合わせて UI 調整できたりって感じ。</p>
<p>僕は Fediverse に来てから、 <a class="reference external" href="https://social.vivaldi.net">Vivaldi Social</a> という Vivaldi が運営する Mastodon 鯖にしばらくいた後、Mastodon でおひとり様自己運営鯖を立ててそこに移り、その後 Firefish にソフトウェア変更を行なって3ヶ月経ったぐらいという感じの変遷をしてる。そこまでまともに比較してないのだけど、Mastodon から Firefish に切り替えた理由は、Mastodon はサービスが3つありおひとり様としては管理コストが大きかった <a class="footnote-reference" href="#maintenance-cost-of-mastodon" id="auto-id-3">[2]</a> のと、Ruby、Node.js 双方のメンテが必要で、メモリも結構サービス自体が食ってくるというのが不満で、そこが改善されてる点で選んでるという感じ。Firefish は Node.js サーバ一つの管理をすればよく、メモリも Mastodon 時代は3サービスそれぞれがそれなりに食ってる状況から大体メモリ消費量半減で管理できるようになった。ただし、ジョブキューの並列数を減らしたりもしたのでここは単純な比較ができなくて眉唾部分もあるかも。とりあえず、現状の Firefish 運用で僕はそれなりに満足しているという感じ。</p>
</div>
<div class="section" id="deb">
<h2>deb の作成<a class="headerlink" href="#deb" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>そんな Firefish だが、インストールにはちょっと難がある。Firefish は一部サーバライブラリを Rust 化しているのだが、このビルドにかなりリソースが必要になる。一部インストール方法の紹介では、ビルド用に CPU リソースを増やしましょうなどと書かれているぐらいだ。さらにこのビルドが遅いため、オンプレ直置き、直ビルドで運用している鯖ではアップデートでの停止時間がそれなりに必要となる。Docker を使えばこの点は解決するが、Docker はそれなりにオーバーヘッドがかかり、運用にも手間がかかる。おひとり様としては、ある程度ルーズに、消費リソースも抑えつつ、ソース管理はいい感じの機構に任せたい。</p>
<p>そこで、僕は deb パッケージを GitHub Actions で作成し、ソースインストール・更新などは Debian 上で apt 経由で行えるようにしている。ソースは <a class="reference external" href="https://github.com/mizunashi-mana/firefish-dist-pkg">https://github.com/mizunashi-mana/firefish-dist-pkg</a>。GitHub Actions 上で前もって npm パッケージ、Rust ソースのビルドなどを行なっておき、それを deb アーカイブにまとめておいて、鯖上には deb をダウンロードして apt 経由でインストールするという感じだ。ついでに、systemd service を付属させたりして、更新時にサービス停止と再起動が行われるようにしたり、サンドボックス機能でセキュリティを強化したり、キャッシュファイルなどの置き場をソースから切り離したりしている。</p>
<p>deb のパッケージ構成用ファイル群は <a class="reference external" href="https://github.com/mizunashi-mana/firefish-dist-pkg/tree/v1.0.5%2Brc-d202312060003%2Brelease/deb/files">https://github.com/mizunashi-mana/firefish-dist-pkg/tree/v1.0.5%2Brc-d202312060003%2Brelease/deb/files</a> らへんにあって、主なファイルとしては</p>
<dl class="docutils">
<dt><a class="reference external" href="https://github.com/mizunashi-mana/firefish-dist-pkg/blob/v1.0.5%2Brc-d202312060003%2Brelease/deb/files/control">control</a></dt>
<dd>deb パッケージのメタ情報。Firefish の依存パッケージである ffmpeg、libvips を指定して、標準リポジトリから自動でインストールされるようにしていたりする。</dd>
<dt><a class="reference external" href="https://github.com/mizunashi-mana/firefish-dist-pkg/blob/v1.0.5%2Brc-d202312060003%2Brelease/deb/files/rules">rules</a></dt>
<dd>deb パッケージのビルドルール。deb パッケージ作成時のタスク内容を記述している。</dd>
<dt><a class="reference external" href="https://github.com/mizunashi-mana/firefish-dist-pkg/blob/v1.0.5%2Brc-d202312060003%2Brelease/deb/files/service">service</a></dt>
<dd>systemd service ファイル。deb パッケージ作成時に deb パッケージに含める。サンドボックス機能をいい感じに有効化したり、書き込み可能なパスなどを制限することで、Firefish に脆弱性などがあった場合の影響を抑えられるようにしている。</dd>
</dl>
<p>みたいな感じ。ま、この辺の詳細は <a class="reference external" href="https://www.debian.org/doc/manuals/debmake-doc/index.ja.html">Debian メンテナー用ガイド</a> らへんを参照してくれ。</p>
<p>このパッケージをインストールすると、</p>
<dl class="docutils">
<dt><tt class="docutils literal">/var/lib/firefish/live</tt></dt>
<dd>Firefish のソース群が置かれる。Firefish は、 <tt class="docutils literal">./files</tt> に画像ファイルなどを置くがこのパッケージではそこを <tt class="docutils literal">/var/lib/firefish/files</tt> へのリンクとしていて実際の書き込みはそっちに行われるため、 <tt class="docutils literal">/var/lib/firefish/live</tt> は完全にリードオンリーでソースファイルのみが置かれる感じになる。また、Firefish は <tt class="docutils literal"><span class="pre">./.config/default.yml</span></tt> を設定ファイルとして参照するが、これも Debian の設定ファイルのディレクトリ構成に合わせて <tt class="docutils literal">/etc/firefish/config.yml</tt> へのリンクとしていて、 <tt class="docutils literal">/etc/firefish</tt> 以下のファイルをいじればいいようにしている。</dd>
<dt><tt class="docutils literal">/var/lib/firefish/files</tt></dt>
<dd>上述の通り、S3 ストレージを設定していない場合のデフォルトの画像ファイル、キャッシュファイルなど置き場。</dd>
<dt><tt class="docutils literal">/var/lib/firefish/work</tt></dt>
<dd>Firefish の実行ユーザのホームディレクトリで、npm などが色々ファイルを生成する場合に使われる。</dd>
<dt><tt class="docutils literal">/etc/firefish</tt></dt>
<dd>Firefish の設定ファイル置き場。</dd>
<dt><tt class="docutils literal">/lib/systemd/system/firefish.service</tt></dt>
<dd>systemd サービスファイル。上記のファイルがインストールされるところ。</dd>
</dl>
<p>などが作成される。またこれらのファイルは新しい deb ファイルをインストール際自動で更新される (設定ファイルなどは更新するか聞かれる) ようになる。実際これを使って3ヶ月ぐらい運用しているが、結構便利。更新もコマンド一発でできるし。あまり真面目にメンテはしてないが、よかったら使ってみてくれって感じ。</p>
</div>
<div class="section" id="auto-id-4">
<h2>インストール方法<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>では、deb ファイルを使う場合のオンプレ直置きでの Firefish インストール方法を、具体的に1から説明していく。今回は Debian 12 (bookworm) での説明になるが、Ubuntu でも大体同じような感じでできるはず。</p>
<p>Debian 12 を ISO インストーラを使ってインストールし、SSH でログインできるようにし、ファイアウォールなどは設定済みの状態を前提にする。これはそれぞれのホスティングサービスによりいい感じのやり方があると思うので、それぞれ調べて欲しいが、 <a class="reference external" href="https://docs.joinmastodon.org/admin/prerequisites/">Mastodon のマシン設定ガイド</a> らへんも参考にするのがいいんじゃないだろうか。僕の場合は、さくら VPS で Debian 12 の標準イメージを使い Debian をインストールした後、</p>
<ol class="arabic simple">
<li>SSH 用の公開鍵を入れて、SSH サーバで攻撃トラフィック低減のためのポート変更と Pubkey 認証以外の無効化を実行。</li>
<li>fail2ban を入れ、sshd 用の設定を有効化。</li>
<li>nftables でファイアウォール設定。</li>
</ol>
<p>をしている。nftables で <a class="reference external" href="https://docs.joinmastodon.org/admin/prerequisites/">Mastodon のマシン設定ガイド</a> と同等のものを設定するには、</p>
<pre class="literal-block">
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
# The default policy of inbound is dropping.
policy drop;
# Allow all loopback (lo0) traffic and drop all traffic to local addresses that doesn't use lo0
iif lo accept;
ip saddr 127.0.0.0/8 iif != lo reject;
ip6 saddr ::1/128 iif != lo reject;
# Accept all established inbound connections
ct state { established, related } accept;
# Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL).
tcp dport { 80, 443 } accept;
# Allow SSH connections
# The -dport number should be the same port number you set in sshd_config
ct state new tcp dport 22 accept;
# Allow ping
icmp type echo-request accept;
ip protocol ipv6-icmp accept;
# Allow destination unreachable messages, especially code 4 (fragmentation required) is required or PMTUD breaks
icmp type destination-unreachable accept;
# Log iptables denied calls
limit rate 5/minute burst 5 packets log prefix "nftables denied: " level debug;
}
chain forward {
type filter hook forward priority 0;
# The default policy of forward is dropping.
policy drop;
}
chain output {
type filter hook output priority 0;
# Allow all outbound traffic - you can modify this to only allow certain traffic
policy accept;
}
}
</pre>
<p>を <tt class="docutils literal">/etc/nftables.conf</tt> に書き込んで (SSH ポート番号 22 の部分は変更している場合は正しいポートに直す必要がある)、 <tt class="docutils literal">systemctl restart nftables</tt> すればいいだろう。若干、icmpv6 パケット全許可だったりするのが気になるが、ひとまずはこれでいいんじゃないだろうか。Ubuntu の場合は ufw とか使うのが普通だと思うので、無理に</p>
<p>またドメインの取得と設定も前提にする。僕は <a class="reference external" href="https://www.cloudflare.com/ja-jp/products/registrar/">Cloudflare Registrar</a> 経由でドメインを買い、そのサブドメインに A レコードと AAA レコードを生やしている。まこの辺はいい感じのサービス見つけるなり、上級者向けだが自分で DNS サーバ立てるなりしてくれ。</p>
<p>その前提で、まず Node.js v20 インストール用の準備をしておく。<a class="reference external" href="https://github.com/nodesource/distributions#installation-instructions">https://github.com/nodesource/distributions#installation-instructions</a> に沿って、インストールを進めていく。具体的には、</p>
<pre class="literal-block">
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
NODE_MAJOR=20
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
sudo apt update
</pre>
<p>を実行する <a class="footnote-reference" href="#nodesource-setup-flow" id="auto-id-5">[3]</a>。</p>
<p>次に、Firefish のデータベース用に Redis と PostgreSQL をインストールして起動しておく:</p>
<pre class="literal-block">
sudo apt install -y redis-server postgresql-15
sudo systemctl restart redis-server
sudo systemctl restart postgresql
sudo systemctl enable redis-server # 再起動時に自動起動するようにする
sudo systemctl enable postgresql # 再起動時に自動起動するようにする
</pre>
<p>そして、Firefish データベース用の PostgreSQL ユーザとデータベースを作成する:</p>
<pre class="literal-block">
sudo -u postgres createuser firefish-user --pwprompt
sudo -u postgres psql -c "CREATE DATABASE firefish OWNER 'firefish-user' ENCODING 'UTF-8';"
</pre>
<p>次に、Firefish パッケージをダウンロードして、インストールする。<a class="reference external" href="https://github.com/mizunashi-mana/firefish-dist-pkg/releases">https://github.com/mizunashi-mana/firefish-dist-pkg/releases</a> からインストールしたいバージョン、基本は最新の自分が使っているディストリビューション用の deb ファイルをダウンロードして、apt 経由でインストールする。具体的には、<a class="reference external" href="https://github.com/mizunashi-mana/firefish-dist-pkg/releases/tag/v1.0.5%2Brc-d202312060003%2Brelease">https://github.com/mizunashi-mana/firefish-dist-pkg/releases/tag/v1.0.5%2Brc-d202312060003%2Brelease</a> の Debian bookworm 用の deb をインストールする場合は</p>
<pre class="literal-block">
curl -L https://github.com/mizunashi-mana/firefish-dist-pkg/releases/download/v1.0.5%2Brc-d202312060003%2Brelease/debian-bookworm-amd64_firefish.deb --output firefish.deb
sudo apt install -y ./firefish.deb
</pre>
<p>すればいい。後は設定を弄って、Firefish の立ち上げを行う。設定は <tt class="docutils literal">/etc/firefish/config.yml</tt> を編集する。まず、ドメイン部分を正しいものに修正する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="gd">- url: https://example.com/</span>
<span class="gi">+ url: https://<使うドメインをここに書く>/</span>
</pre></div></td></tr></table></div>
<p>それから PostgreSQL の設定を修正する。データベース名、ユーザ名、パスワードを先程作成したものに修正する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div><pre><span></span><span class="w"> </span> db:
<span class="w"> </span> host: localhost
<span class="w"> </span> port: 5432
<span class="w"> </span> #ssl: false
<span class="w"> </span> # Database name
<span class="w"> </span> db: firefish
<span class="w"> </span> # Auth
<span class="gd">- user: example-firefish-user</span>
<span class="gd">- pass: example-firefish-password</span>
<span class="gi">+ user: firefish-user</span>
<span class="gi">+ pass: <先程設定したパスワードをここに書く></span>
<span class="w"> </span> # Whether disable Caching queries
<span class="w"> </span> #disableCache: true
</pre></div></td></tr></table></div>
<p>後は適宜弄りたい設定があったらいじる。個人的に、Redis の prefix を設定しておくのがおすすめだ。これは新たに Redis を使う他のサーバが生まれた時に同居させやすいからだ。ま、そういう予定がなければ特に弄らなくてもいいだろう。ここまで出来たら、Firefish を起動する:</p>
<pre class="literal-block">
sudo systemctl restart firefish
sudo systemctl enable firefish # 再起動時に自動起動するようにする
</pre>
<p>次に Firefish の管理者ユーザを作成しておく。これは後ででもいいが、セキュリティ的にはここで作っておくのが安全だ。SSH でポートフォワーディングして、ブラウザから作成するのがおすすめだ。まずサーバ内でなく手元で以下を実行して、ポートフォワーディングを行う:</p>
<pre class="literal-block">
ssh -L 3000:localhost:3000 <接続先ホスト>
</pre>
<p>これにより、<a class="reference external" href="http://localhost:3000">http://localhost:3000</a> にブラウザでアクセスすると、Firefish の管理者ユーザ作成画面が立ち上がる。後はユーザ名とパスワードを入力して、管理者ユーザを作成する。このユーザで以降投稿などができるようになる。</p>
<p>次に、リバースプロキシの用意と TLS 化を行う。ここら辺は、レジストラサービスに付随していたりもするので、そっちを使う場合は不要になる。自前で用意する場合は、まず Nginx のインストールを行う:</p>
<pre class="literal-block">
sudo apt install -y nginx
</pre>
<p>その後、以下のような設定を <tt class="docutils literal"><span class="pre">/etc/nginx/sites-available/firefish.conf</span></tt> に書き込む:</p>
<pre class="literal-block">
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream firefish {
server localhost:3000 fail_timeout=0;
}
proxy_cache_path
/var/cache/nginx/firefish
levels=1:2
keys_zone=cache_firefish:16m
inactive=720m
max_size=1g
use_temp_path=off
;
server {
listen 80;
listen [::]:80;
server_name <使うドメインをここに書く>;
root /var/www/html/firefish;
location /.well-known/acme-challenge/ {
allow all;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
# TLS 設定をした後、以下のコメントアウトを外す
listen 127.0.0.1:443;
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# ssl_certificate /path/to/fullchain.pem;
# ssl_certificate_key /path/to/privkey.pem;
server_name <使うドメインをここに書く>;
# You can use https://ssl-config.mozilla.org/ to generate your cipher set.
# We recommend their "Intermediate" level.
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
keepalive_timeout 70;
sendfile on;
client_max_body_size 99m;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml image/x-icon;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# For WebSocket
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
location / {
proxy_pass http://firefish;
# Cache settings
proxy_cache cache_firefish;
proxy_cache_lock on;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache $upstream_cache_status;
}
}
</pre>
<p>それから、キャッシュ用のディレクトリ作成と、Nginx 設定の有効化を行う:</p>
<pre class="literal-block">
sudo mkdir -p /var/cache/nginx
sudo chown www-data:www-data /var/cache/nginx
sudo ln -s /etc/nginx/sites-available/firefish.conf /etc/nginx/sites-enabled/firefish.conf
sudo rm -rf /etc/nginx/sites-enabled/default # デフォルトの設定を無効化
sudo systemctl restart nginx
sudo systemctl enable nginx # 再起動時に自動起動するようにする
</pre>
<p>次に TLS 証明書をインストールする。証明書をどっかで買ってる場合は、それをダウンロードしてくる。証明書に拘りがなく、とりあえず TLS 化だけしたい場合は、Let's Encrypt を利用するといいだろう。ここでは、Let's Encrypt を使う場合の設定を説明する。まず、certbot をインストールして、証明書発行を行う:</p>
<pre class="literal-block">
sudo apt install -y certbot python3-certbot-nginx
sudo certbot certonly --nginx -d <使うドメインをここに書く> --post-hook "systemctl reload nginx"
sudo systemctl enable certbot.timer # 証明書の自動更新を有効化する
</pre>
<p>TLS 証明書をダウンロードしたら、Nginx の設定ファイルを修正して、TLS 証明書を読み込むようにする:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="gd">- # TLS 設定をした後、以下のコメントアウトを外す</span>
<span class="gd">- listen 127.0.0.1:443;</span>
<span class="gd">- # listen 443 ssl http2;</span>
<span class="gd">- # listen [::]:443 ssl http2;</span>
<span class="gd">- # ssl_certificate /path/to/fullchain.pem;</span>
<span class="gd">- # ssl_certificate_key /path/to/privkey.pem;</span>
<span class="gi">+ listen 443 ssl http2;</span>
<span class="gi">+ listen [::]:443 ssl http2;</span>
<span class="gi">+ ssl_certificate /etc/letsencrypt/live/<使うドメインをここに書く>/fullchain.pem;</span>
<span class="gi">+ ssl_certificate_key /etc/letsencrypt/live/<使うドメインをここに書く>/privkey.pem;</span>
</pre></div></td></tr></table></div>
<p>上記は Let's Encrypt の証明書を使う場合だが、独自の証明書を使う場合はその証明書の秘密鍵と中間証明書のパスを設定するようにする。そして、Nginx を再起動する:</p>
<pre class="literal-block">
sudo systemctl restart nginx
</pre>
<p>ここまで上手くいったら、ブラウザで <a class="reference external" href="https:/">https:/</a>/<使うドメイン>/ にアクセスして、Firefish の画面が表示されることを確認する。これで、Firefish のインストールは完了となるはず。後は、更新があったらまた deb をダウンロードしてきて、 <tt class="docutils literal">sudo apt install <span class="pre">-y</span> ./firefish.deb</tt> で更新できる。</p>
<p>うまく行かなかったら、その時はまあ頑張ってくれ。 <a class="reference external" href="https://wiki.sabakan.industries/">鯖缶工場</a> という分散 SNS のサーバ管理者の寄合所帯があるので、そこに助け求めると誰かが助けてくれるかもしれない。</p>
</div>
<div class="section" id="auto-id-7">
<h2>まとめ<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、Firefish の紹介と、そのインストール方法を紹介した。多分、あまり Firefish を直でインストールする系の記事はないと思うので、それを放流しておくのも兼ねてという感じ。何かの参考になれば。</p>
<p>この先、deb 配布を真面目にメンテしていくかは分からないが、ひとまず自分で使ってるので僕が Firefish ユーザを辞めない限りは続けていくんじゃないだろうか。何か要望があれば、言って貰えばすぐ対応できるものなら対応するかもしれない。というわけで、今回はそんな感じで。</p>
<table class="docutils footnote" frame="void" id="support-status-mastodon-api-of-firefish" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>使えると言っても若干更新が追いついていなかったり、対応が不完全だったりするので、完全に Mastodon 用のクライアントアプリが使えるというわけではない。また、Mastodon 用のクライアントアプリを使う場合、Firefish 用の機能を使えない場合があるので注意が必要。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="maintenance-cost-of-mastodon" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[2]</a></td><td>逆に大手だとそれぞれでスケーリングできるので、サービス分かれてる方が嬉しいかもしれない。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="nodesource-setup-flow" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[3]</a></td><td>たまにインストール方法が変わってることがあるので、nodesource の README の方をまずは参照して欲しい。</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/12/install-firefish-by-deb.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/12/install-firefish-by-deb.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>2023/10 時点の Fediverse の状況2023-10-29T04:45:15+09:002023-10-29T04:45:15+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-10-29:/blog/posts/2023/10/fediverse-stats/<p>Fediverse は、W3C 勧告の ActivityPub を主要なプロトコルとした、リソース共有を相互に行う Web 上の分散ネットワークである。昨今の騒動 …</p><p>Fediverse は、W3C 勧告の ActivityPub を主要なプロトコルとした、リソース共有を相互に行う Web 上の分散ネットワークである。昨今の騒動で分散 SNS としてそれなりの人口を抱えており、僕は今年の2月ぐらい移住していて、かれこれ8ヶ月になる。</p>
<p>さて、Fediverse はオープン規格で構成されているため、基本的なデータは割と簡単に手に入れることができる。今回は、そのデータをちょっと整理して、現状の Fediverse の状況を見てみようと思う。</p>
<div class="section" id="auto-id-1">
<h2>インスタンスごとの情報をとる<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Fediverse 上で情報集める方法は幾つかあるが、ネットワーク内のノード、つまりサーバ単位で情報を集めるには以下が使える:</p>
<dl class="docutils">
<dt><tt class="docutils literal">nodeinfo</tt>: <a class="reference external" href="https://nodeinfo.diaspora.software/">https://nodeinfo.diaspora.software/</a></dt>
<dd>Fediverse でサーバの実行状態を公開する標準的な方法を目指した規格。JLD の拡張で、 <tt class="docutils literal"><span class="pre">/.well-known/nodeinfo</span></tt> というエンドポイントに JSON リソースリンクを公開し、そのリンク先に定められた形式でメトリクスを出すという形。ソフトウェア情報、登録機能が解放されているか、ユーザ数、投稿数などが取れる。</dd>
<dt><tt class="docutils literal">manifest.json</tt>: <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json</a></dt>
<dd>PWA に対応しているサーバでは、それ用のマニフェストファイルに色々特定の形式で情報を載せている。ここから、サーバ名や説明などが取れる。</dd>
<dt>Mastodon Instance API: <a class="reference external" href="https://docs.joinmastodon.org/methods/instance/">https://docs.joinmastodon.org/methods/instance/</a></dt>
<dd>Fediverse では Mastodon API が割と事実上の標準となっているところがあり、Mastodon API と互換のある形式で API 公開してるところも多い。そういうところなら、対応していれば Mastodon Instance API で <tt class="docutils literal">nodeinfo</tt> 以上の情報が取れる。具体的には、 <tt class="docutils literal">nodeinfo</tt> で取れる情報に加えて、対応言語、連絡先、サーバ名、サーバのルール、連合先ホストなど。</dd>
<dt>OGP (Open Graph Protocol): <a class="reference external" href="https://ogp.me/">https://ogp.me/</a></dt>
<dd>Web で事実上の標準となっている、Web ページのメタ情報の規格。サーバ名や説明などが取れる。</dd>
</dl>
<p>他にもソフトウェア固有のものがいくつかあるが、全般的に取れるのはこんぐらいだろう。今回はこのうち、 <tt class="docutils literal">nodeinfo</tt> と Mastodon Instance API の連合先ホスト一覧をとる機能のみを使っていく。具体的に見ていこう。</p>
<p>まず、 <tt class="docutils literal">nodeinfo</tt> だが、これは <tt class="docutils literal"><span class="pre">/.well-known/nodeinfo</span></tt> から以下のような JSON を取ってくる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"links"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"rel"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://nodeinfo.diaspora.software/ns/schema/2.1"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"href"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://ff.mizunashi.work/nodeinfo/2.1"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"rel"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://nodeinfo.diaspora.software/ns/schema/2.0"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"href"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://ff.mizunashi.work/nodeinfo/2.0"</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal"><span class="pre">/.well-known/nodeinfo</span></tt> には <tt class="docutils literal">links</tt> フィールドに <tt class="docutils literal">nodeinfo</tt> リソース URL の配列を公開することになっている。配列の要素は <tt class="docutils literal">rel</tt> 要素にスキーマ、 <tt class="docutils literal">href</tt> 要素にリソース URL を書く。 <tt class="docutils literal">nodeinfo</tt> は現在 1.0、1.1、2.0、2.1 が出ており、1.x と 2.x は一部フィールドは互換がないが、基本的にはフィールド追加が主になる。なお、リソース URL は <tt class="docutils literal"><span class="pre">/nodeinfo/<version></span></tt> みたいな形式になってるソフトは多いが、基本どういう URL であっても良い。 <tt class="docutils literal"><span class="pre">/nodeinfo/<version>.json</span></tt> みたいな URL で公開してるとこも多い。</p>
<p><tt class="docutils literal">nodeinfo</tt> リソースの内容は、 <a class="reference external" href="http://nodeinfo.diaspora.software/ns/schema/2.1">http://nodeinfo.diaspora.software/ns/schema/2.1</a> を見てもらうのがいいかもしれないが、一応見ておくと、以下のような情報が取れる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.1"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"software"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"firefish"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0.4-beta31"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"repository"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://codeberg.org/firefish/firefish"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"homepage"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://joinfirefish.org/"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"protocols"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"activitypub"</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">"services"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"inbound"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span>
<span class="w"> </span><span class="nt">"outbound"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"atom1.0"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"rss2.0"</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"openRegistrations"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"usage"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"users"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"total"</span><span class="p">:</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"activeHalfyear"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"activeMonth"</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"localPosts"</span><span class="p">:</span><span class="w"> </span><span class="mi">436</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"localComments"</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"metadata"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"nodeName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Mizunashi Social"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"nodeDescription"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Mizunashi Mana のおひとり様サーバです。日本国法を遵守して、運用していく所存です。"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"maintainer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Mizunashi Mana"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"email"</span><span class="p">:</span><span class="w"> </span><span class="s2">"contact@mizunashi.work"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"langs"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span>
<span class="w"> </span><span class="nt">"tosUrl"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"repositoryUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://codeberg.org/firefish/firefish"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"feedbackUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://codeberg.org/firefish/firefish/issues"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"disableRegistration"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"disableLocalTimeline"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"disableRecommendedTimeline"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"disableGlobalTimeline"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"emailRequiredForSignup"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"searchFilters"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"postEditing"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"postImports"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"enableHcaptcha"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"enableRecaptcha"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"maxNoteTextLength"</span><span class="p">:</span><span class="w"> </span><span class="mi">3000</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"maxCaptionTextLength"</span><span class="p">:</span><span class="w"> </span><span class="mi">1500</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"enableTwitterIntegration"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"enableGithubIntegration"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"enableDiscordIntegration"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"enableEmail"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"enableServiceWorker"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"proxyAccountName"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"themeColor"</span><span class="p">:</span><span class="w"> </span><span class="s2">"#31748f"</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>これは僕の Firefish というソフトウェアの鯖での実際の値なのだが、ソフトウェア情報とか、アカウント登録解放してるかとか、ユーザ数・投稿数などが JSON フィールドで公開されている。なお、 <tt class="docutils literal">metadata</tt> フィールドにも色々書いてあるが、これはソフトウェア独自拡張で、それぞれのソフトウェアに依るという感じ。今回の分析は、基本この拡張以外の情報だけを見ていくという感じ。拡張の方はちょっと対応状況が悪いので、もうちょっと別の情報源当たった方がいいかなという感じ。</p>
<p>さて、Fediverse は広大なネットワークでノードも大小ある。そのため、ノードが特定できた場合に情報を取得する方法があっても、そもそもノードを見つけなければ意味がない。そこでノードの探索方法も重要になる。ノードの探索は多分確立した方法はないが、対応状況が現状一番良いのは Mastodon Instance API の連合先一覧取得、 <a class="reference external" href="https://docs.joinmastodon.org/methods/instance/#peers">/api/v1/instance/peers</a> だと思われる。対応状況は後でみるが、こいつもそこまで対応状況が良いとは言えず、大手の <a class="reference external" href="https://join-lemmy.org/">Lemmy</a>、 <a class="reference external" href="https://joinpeertube.org/">PeerTube</a> といったソフトウェアは独自の API を叩くしかないという状況だ。今回は対応してるとこのみ探索してるが、その内もうちょっと個々の API 当たれるようにはしてみたいとは思っている。さて、具体的な方法だが、 <tt class="docutils literal">/api/v1/instance/peers</tt> を叩くと以下のような JSON が返ってくるので、これを取るだけ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">[</span>
<span class="w"> </span><span class="s2">"ff.mizunashi.work"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"misskey.io"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"mastodon.social"</span>
<span class="p">]</span>
</pre></div></td></tr></table></div>
<p>それぞれはホスト名になっており、ここの連合先をさらに辿っていけば、ひとまず Fediverse の大部分は網羅できるだろうというわけだ。</p>
</div>
<div class="section" id="auto-id-2">
<h2>情報取得精度と対応状況<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、実際に nodeinfo と peers API から情報収集を行うクローラーを書いた: <a class="reference external" href="https://github.com/mizunashi-mana/fediverse-stats">https://github.com/mizunashi-mana/fediverse-stats</a></p>
<p>最初のインスタンスホストを与えれば、大体一日かけて Fediverse 上のデータを集めてくれる。10/22 時点での情報取得状況は以下だった:</p>
<table border="1" class="docutils">
<colgroup>
<col width="33%"/>
<col width="33%"/>
<col width="33%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">取得状況</th>
<th class="head">ホスト数</th>
<th class="head">割合</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>成功</td>
<td>23813</td>
<td>30.43%</td>
</tr>
<tr><td>失敗</td>
<td>54451</td>
<td>69.57%</td>
</tr>
</tbody>
</table>
<p>辿った先の半数以上のホストでは情報取得に失敗したが、23813件分のインスタンス情報は集まったらしい。情報取得失敗理由についてもう少し見てみると以下のようになった:</p>
<table border="1" class="docutils">
<colgroup>
<col width="57%"/>
<col width="22%"/>
<col width="22%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">失敗理由</th>
<th class="head">ホスト数</th>
<th class="head">割合</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>アドレス解決失敗</td>
<td>19105</td>
<td>35.09%</td>
</tr>
<tr><td>nodeinfo 404 Not Found</td>
<td>9584</td>
<td>17.60%</td>
</tr>
<tr><td>TLS 証明書検証失敗</td>
<td>6104</td>
<td>11.21%</td>
</tr>
<tr><td>TCP 接続未達</td>
<td>5680</td>
<td>10.43%</td>
</tr>
<tr><td>タイムアウト (10sec)</td>
<td>4233</td>
<td>7.77%</td>
</tr>
<tr><td>無効な HTTP ステータス</td>
<td>3747</td>
<td>6.88%</td>
</tr>
<tr><td>nodeinfo の形式違反</td>
<td>1981</td>
<td>3.64%</td>
</tr>
</tbody>
</table>
<p>アドレス解決失敗は一時的なものか一時的なものかの判別は困難だが、ほとんどは恒久的なものだろう。TLS 証明書検証失敗や、TCP 接続未達についても同じことが言える。というわけで半分はおそらくインスタンスが既に閉鎖していることによるものだと思われる。nodeinfo の HTTP ステータスコード違反、形式違反については数が多くて全部は見れていないが、こちらも基本的にインスタンスが既に閉鎖していて別のサービスに置き換わっていることによるものが多そうだ。ただ、一部 nodeinfo を公開していない独自インスタンスがあったり、全体に SSO 認証を敷いているサーバがあったりするようだ。もう少し今後詳細を調べていきたいが、ひとまずそこまで大きく逃しているノードは無いように思える。</p>
<p>一応上位の有名サーバが情報取得済みの対象に含まれていることも確認しておく。ユーザ数上位10件は以下のようになっている:</p>
<table border="1" class="docutils">
<colgroup>
<col width="36%"/>
<col width="17%"/>
<col width="15%"/>
<col width="22%"/>
<col width="10%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">URL</th>
<th class="head">ソフトウェア</th>
<th class="head">ユーザ数</th>
<th class="head">月間活動ユーザ数</th>
<th class="head">連合数</th>
</tr>
</thead>
<tbody valign="top">
<tr><td><a class="reference external" href="https://egirls.gay/">https://egirls.gay/</a></td>
<td>misskey</td>
<td>1234567890</td>
<td>不明</td>
<td>2617</td>
</tr>
<tr><td><a class="reference external" href="https://mastodon.social/">https://mastodon.social/</a></td>
<td>mastodon</td>
<td>1644665</td>
<td>283606</td>
<td>63812</td>
</tr>
<tr><td><a class="reference external" href="https://pawoo.net/">https://pawoo.net/</a></td>
<td>mastodon</td>
<td>925128</td>
<td>49238</td>
<td>37460</td>
</tr>
<tr><td><a class="reference external" href="https://daystorm.netz.org/">https://daystorm.netz.org/</a></td>
<td>mastodon</td>
<td>479002</td>
<td>479003</td>
<td>不明</td>
</tr>
<tr><td><a class="reference external" href="https://mstdn.jp/">https://mstdn.jp/</a></td>
<td>mastodon</td>
<td>401999</td>
<td>38723</td>
<td>60633</td>
</tr>
<tr><td><a class="reference external" href="https://misskey.io/">https://misskey.io/</a></td>
<td>mastodon</td>
<td>399443</td>
<td>不明</td>
<td>22124</td>
</tr>
<tr><td><a class="reference external" href="https://joindiaspora.com/">https://joindiaspora.com/</a></td>
<td>diaspora</td>
<td>316111</td>
<td>74</td>
<td>不明</td>
</tr>
<tr><td><a class="reference external" href="https://baraag.net/">https://baraag.net/</a></td>
<td>mastodon</td>
<td>293188</td>
<td>37530</td>
<td>26857</td>
</tr>
<tr><td><a class="reference external" href="https://mastodon.cloud/">https://mastodon.cloud/</a></td>
<td>mastodon</td>
<td>273693</td>
<td>7552</td>
<td>47955</td>
</tr>
<tr><td><a class="reference external" href="https://pravda.me/">https://pravda.me/</a></td>
<td>mastodon</td>
<td>223407</td>
<td>52550</td>
<td>5224</td>
</tr>
</tbody>
</table>
<p>Mastodon 鯖に限って言えば、大体 <a class="reference external" href="https://mastodonservers.net/servers/top">https://mastodonservers.net/servers/top</a> の通りかなと思うので、おそらくそこまで大きな取りこぼしはないと思われる。なお、基本的に今回使う数値は自己申告制なので、悪意ある実装には弱い。実際上の数値はトップの <a class="reference external" href="https://egirls.gay/">https://egirls.gay/</a> と4位の <a class="reference external" href="https://daystorm.netz.org/">https://daystorm.netz.org/</a> は数値が明らかにおかしいため、この後の分析では除外している。他にも詳しく見てみたら除外した方がいい数値はあるかもしれない。ま、そういうわけなので、あくまで参考程度に留めてくれという感じ。</p>
<p>数値取得の対応状況だが、項目毎に見てみると以下のようになる:</p>
<table border="1" class="docutils">
<colgroup>
<col width="41%"/>
<col width="28%"/>
<col width="31%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">項目</th>
<th class="head">対応ホスト数</th>
<th class="head">対応ホスト割合</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>ソフトウェア名</td>
<td>23811</td>
<td>99.99%</td>
</tr>
<tr><td>ソフトウェアバージョン</td>
<td>23795</td>
<td>99.92%</td>
</tr>
<tr><td>ソフトウェアリポジトリ</td>
<td>1963</td>
<td>8.24%</td>
</tr>
<tr><td>ユーザ登録解放状況</td>
<td>23803</td>
<td>99.95%</td>
</tr>
<tr><td>ユーザ数</td>
<td>23163</td>
<td>97.27%</td>
</tr>
<tr><td>半年間活動ユーザ数</td>
<td>17675</td>
<td>74.22%</td>
</tr>
<tr><td>月間活動ユーザ数</td>
<td>17782</td>
<td>74.67%</td>
</tr>
<tr><td>ローカル投稿数</td>
<td>22889</td>
<td>96.12%</td>
</tr>
<tr><td>ローカルコメント数</td>
<td>8031</td>
<td>33.73%</td>
</tr>
<tr><td>連合ホスト数</td>
<td>14970</td>
<td>62.86%</td>
</tr>
</tbody>
</table>
<p>nodeinfo/1.0 の時点で必須だった、ソフトウェア名、ソフトウェアバージョン、ユーザ登録解放状況は総じて対応状況が良い。また、ユーザ数、投稿数は必須ではないが公開してくれてるとこが多い。ただ、半年間活動 (アクティブ) ユーザ数、月間活動ユーザ数、コメント数は対応が少し悪い。nodeinfo/2.1 から入ったソフトウェアリポジトリもまだまだ対応してるとこは少ないという感じだ。連合ホスト数は、nodeinfo では対応してなくて、peers API からカウントして出している。これはいわば Mastodon Instance Peers API に対応してたかどうかの数になる。こちらも半数以上は対応してるが対応状況は良くはないということになる。なお、連合ホスト数には罠があり、大体それぞれのホストで連合先のソフトウェアにはホストと同じソフトウェアが使われているという偏りがある。そのため、Lemmy、PeerTube といったソフトウェアのネットワークは取りこぼしが発生している可能性が高く、逆に言えば Mastodon Instance Peers API に対応している範囲のネットワークしか拾えていないため対応状況が半数超えてるように見えているという可能性がある。その辺は将来的に少し改善していきたいところだが、ひとまず今回はこのデータを元に見ていく。</p>
</div>
<div class="section" id="auto-id-3">
<h2>Fediverse の状況<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ではそれぞれの数値を見ていこう。まず、総計値は以下のようになる:</p>
<table border="1" class="docutils">
<colgroup>
<col width="59%"/>
<col width="41%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">項目</th>
<th class="head">総計</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>インスタンス数</td>
<td>23811</td>
</tr>
<tr><td>ユーザ数</td>
<td>11555114</td>
</tr>
<tr><td>半年間活動ユーザ数</td>
<td>3364984</td>
</tr>
<tr><td>月間活動ユーザ数</td>
<td>1333071</td>
</tr>
<tr><td>ローカル投稿数</td>
<td>1164902338</td>
</tr>
<tr><td>ローカルコメント数</td>
<td>25175892</td>
</tr>
</tbody>
</table>
<p>もちろん対応状況がまちまちなので、これらは確度の低い最低値ぐらいの認識でいるのがいいだろう。人口としてグローバルで1000万というのは、X が3億、YouTube が20億、Facebook が30億という数値から見るとまだやっぱり規模としては小さい <a class="footnote-reference" href="#sns-users-press" id="auto-id-4">[1]</a>。またこの中にはかなり休眠ユーザもいるはずだ。月間活動ユーザ数は対応してない大規模インスタンスもいくつかいるので、おそらくこれよりは多いはずだが、それでも桁として変わることはないだろうから実質稼働しているユーザは数百万程という感じだろう。こちらは Facebook が2600万、X が 4500 万らしい <a class="footnote-reference" href="#sns-users-press" id="auto-id-5">[1]</a> ので、やはり規模の桁は違うものの規模としては追いつける余地は十分ありそうだ。というわけで、現状ユーザ規模としては大手と比べるとまだまだだが、小さすぎるというわけでもなさそうという感じ。</p>
<p>次にそれぞれの分布を見てみる。まずインスタンス毎のユーザ数分布を見てみる:</p>
<img alt="インスタンス毎のユーザ数分布" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/users_per_image.png"/>
<p>この分布図は、数値を昇順に並べた場合に、横軸の割合の位置にいる数値が縦軸に対応する。見方としては、例えば横軸50の位置の縦軸数値が3だが、これは昇順に並べた場合に真ん中の位置にいる数値が3、つまり中央値は3であるということを意味する。ここから、大体中央値がユーザ数3ぐらい、75%ぐらいのインスタンスはユーザ数10以下のインスタンスという感じになる。75%を超えた辺りから結構ユーザ数が増加するという感じで、1/4程が盛況という感じのようだ。逆に1/4はおひとり様という感じっぽい。次にインスタンス毎の投稿数分布を見てみる:</p>
<img alt="インスタンス毎の投稿数分布" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/posts_per_image.png"/>
<p>ユーザ数分布に比べてインスタンス毎に数が結構違うっぽい。中央値は200ぐらいで、75%のインスタンスは投稿数2000以下のようだ。思ったより廃人やボットは少ないかもしれない。大半は、程々の投稿を抱えてるって感じっぽい。次にインスタンス毎の連合数分布を見てみる:</p>
<img alt="インスタンス毎の連合数分布" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/peers_per_image.png"/>
<p>75%以上のインスタンスは、連合数100以上という感じっぽい。ユーザ数の分布で見た通り、基本的におひとり様かある程度のユーザ規模のインスタンスが多いので、フォロー・フォロワー数もある程度の規模のインスタンスが大半という感じなのだろう。最後にインスタンス毎の月間活動ユーザ数分布を見てみる:</p>
<img alt="インスタンス毎の月間活動ユーザ数分布" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/users_active_month_per_image.png"/>
<p>この数値はソフトウェアにより対応状況が悪いというのはあるが、ユーザ数分布に比べて冬眠ユーザ、仮想ユーザを除いた数値が見れるのでより実態に近しい数値分布として使えるだろう。これを見ると、半分以上のインスタンスは実質1ユーザということになる。また75%でも4ユーザ以下しか稼働していないようだ。</p>
<p>次にソフトウェア毎のシェア率を見ていこう。まずインスタンス数のシェア率を見てみる:</p>
<img alt="ソフトウェア毎のインスタンス数シェア率" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/instances_share_by_softwares.png"/>
<p>Mastodon が圧倒的だが、その次が WordPress なのは結構意外だ。WordPress には ActivityPub プラグインがあり、ブログ投稿を Fediverse に配信してくれる。その機能使ってる WordPress 鯖もそれなりにいるっぽい。その後は、Misskey、PeerTube、Pleroma、Lemmy となるようで、この段階でインスタンスの75%以上となるようだ。この辺が大体人気のソフトウェアになるようだ。これはインスタンス数シェアになるので鯖管理人から見た視点になるが、ユーザ視点で言うとユーザ数シェアで見るのが良いだろう。というわけで、ユーザ数シェアも見てみる:</p>
<img alt="ソフトウェア毎のユーザ数シェア率" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/users_share_by_softwares.png"/>
<p>こちらでも Mastodon が圧倒的で、Lemmy、Misskey、Diaspora が続くようだ。ここから、ユーザのうち10人中7人は Mastodon を使っており、残り2人は Lemmy か Misskey、Diaspora のどれか、残り1人はそれ以外のソフトウェアを使っていると言う感じになる。インスタンス数シェア上位だった WordPress、Pleroma が姿を消し、代わりに Lemmy が大きく順位を上げ、Diaspora も躍り出ているという感じだ。WordPress、Pleroma は基本小規模インスタンスで使われることが多いので、ユーザ数シェアで見ると姿を消してしまっている。Diaspora は実はユーザ数で見るとシェアが大きいように見えるが、実はここに関しては JoinDiaspora というインスタンスのユーザがメインになっていて、ここは閉鎖に向かっており投稿を含むほぼ全ての機能が停止されていてユーザも活動していないという状況のようだ。なので、実質 Mastodon、Lemmy、Misskey がユーザから見て認知されてるソフトウェアということになるだろう。なおこれはグローバルで見てるが、日本語投稿が多いインスタンスとかに限定するともう少し変わってくるかもしれない。ただ、そこの判定は地味にめんどいので今回は見てない。</p>
<p>さて、ソフトウェアのシェアはおひとり様か開いたインスタンスかなどのインスタンスの属性によりかなり変わる。そちらも少し見てみる。まず、アカウント登録を解放しているかどうかでのインスタンスシェアを見てみる:</p>
<img alt="アカウント登録を開放しているかによるインスタンス数シェア率" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/instances_share_by_regtypes.png"/>
<p>半分以上がアカウント登録を開放していない閉じたインスタンスで、開いたインスタンスは40%にも満たない。まずアカウント登録を開放しているオープンインスタンスでのソフトウェアシェアを見てみる:</p>
<img alt="ソフトウェア毎のオープンインスタンス数シェア率" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/open_instances_share_by_softwares.png"/>
<p>Mastodon が相変わらず圧倒的だが、オープンインスタンスではユーザシェアと似たようなシェア傾向にあり、WordPress の代わりに Lemmy、Misskey が上位に入っている。また、個人的に意外だったが Pleroma、GoToSocial も割とシェアとしてはある程度あるようだ。逆に稼働ユーザ1のアカウント登録を開放していないインスタンス、通称おひとり様インスタンスでのシェアは以下のようになる:</p>
<img alt="ソフトウェア毎のおひとり様インスタンス数シェア率" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/alone_instances_share_by_softwares.png"/>
<p>こちらも Mastodon が圧倒的だが、それ以降はオープンインスタンスとかなり顔ぶれが変わり、Pleroma、PeerTube、Owncast で75%になるようだ。なお、今回おひとり様の判断は正確にはアカウント登録を開放しておらず、稼働ユーザ数1または稼働ユーザが取れなかったところはユーザ数5以下で判定しているので、正確におひとり様判定できているかは少し怪しい。これは Misskey などでは稼働ユーザ数の対応状況が悪くかつ仮想ユーザが生えてくることがあるためという感じだ。なので、まあそこまで確度は高くない。</p>
<p>最後にもう少し詳しいバージョン情報込みのソフトウェアシェアを見てみる。まずインスタンス数シェアから:</p>
<img alt="バージョン込みのソフトウェア毎インスタンス数シェア率" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/instances_share_by_softwares_with_vers.png"/>
<p>思ったよりみんなバージョン更新ちゃんとやってるようで、Mastodon 最新版のシェアが一番大きく、基本他のインスタンスも4系を使ってるところが多いようだ。ユーザ数シェアも見てみると、以下のようになる:</p>
<img alt="バージョン込みのソフトウェア毎ユーザ数シェア率" src="https://mizunashi-mana.github.io/blog/posts/2023/10/fediverse-stats/fediverse-stats/users_share_by_softwares_with_vers.png"/>
<p>Mastodon 4系、Lemmy 0.18、Misskey (io版)、JoinDiaspora で使われてるバージョンが基本的なシェアを占める。特にユーザの40%以上は Mastodon 4.2 を使ってるっぽいので、その UI 前提という感じっぽい。そこは Fediverse 上での体験の前提として押さえておくのがいいかもしれない。</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、ひとまず Fediverse の各数値について並べてみた。分かることは中々少ないが、ひとまず Mastodon がソフトウェアシェアにおいて圧倒的であること、Fediverse の参加インスタンスは小規模インスタンスメインであることは読み取れる。とはいうものの信頼性に怪しい数値はやはりあるし、もうちょっと数値収集や情報源の拡張には改善の余地がありそうだ。</p>
<p>Fediverse は日々その姿を変えているし、この数値も半年後には大きく変わっているかもしれない。ただ、技術屋としてはオープン規格で色々やりやすく、実験場としての魅力は申し分ないし、SNS としても最近困ることがなくなってきた。むしろ日々色んなところで実験が生まれ、色々体験も変わってくるところはそこを楽しめる人にとっては面白い環境だと思う。結構これからが楽しみだ。</p>
<p>ま、今回の数値が何かの参考になればというわけで、今回はこれで。</p>
<table class="docutils footnote" frame="void" id="sns-users-press" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label">[1]</td><td><em>(<a class="fn-backref" href="#auto-id-4">1</a>, <a class="fn-backref" href="#auto-id-5">2</a>)</em> <a class="reference external" href="https://growthseed.jp/experts/sns/number-of-users/">https://growthseed.jp/experts/sns/number-of-users/</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/10/fediverse-stats.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/10/fediverse-stats.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>ボックスタイプとCSSレイアウト2023-10-08T13:40:38+09:002023-12-06T11:53:49+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-10-08:/blog/posts/2023/10/display-property-of-css/<p>さて、</p>
<div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">div</span><span class="p">></span>デザインにおいて、<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"text-decoration: underline;"</span><span class="p">></span>レイアウト<span class="p"></</span><span class="nt">div</span><span class="p">></span>は重要な要素だ。<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div>
<p>という HTML 片が、基本的なブラウザでどう表示され …</p><p>さて、</p>
<div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">div</span><span class="p">></span>デザインにおいて、<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"text-decoration: underline;"</span><span class="p">></span>レイアウト<span class="p"></</span><span class="nt">div</span><span class="p">></span>は重要な要素だ。<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div>
<p>という HTML 片が、基本的なブラウザでどう表示され、それがどういう原理からくるものか分かるだろうか? そして、それが意図に反した表示になっている場合に、意図通りに直すことはできるだろうか? これに対して明確な答えを持っている人は、この記事に書いてあることを既に理解しているであろうから引き返してなんら問題はない。</p>
<p>結論から言えば、これは</p>
<div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">div</span><span class="p">></span>デザインにおいて、<span class="p"><</span><span class="nt">span</span> <span class="na">style</span><span class="o">=</span><span class="s">"text-decoration: underline;"</span><span class="p">></span>レイアウト<span class="p"></</span><span class="nt">span</span><span class="p">></span>は重要な要素だ。<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div>
<p>と書くのが一つ意図通りの HTML 片だったということになる。 <tt class="docutils literal">div</tt> タグの代わりに、 <tt class="docutils literal">span</tt> タグを使っているところが異なる。実は最初に提示した HTML 片は、基本的なブラウザでは「デザインにおいて、」の後と、「は重要な要素だ。」の前に改行が入るようレンダリングされる。対して、 <tt class="docutils literal">span</tt> タグを使用すると、一行にそのまま表示される。部分的に下線をつけるためだけに <tt class="docutils literal">div</tt> タグを使っていたつもりが、なぜかレイアウトにまで影響を与えていてしまったということだ。</p>
<p>この結果を引き起こす仕様はごく単純なもので、CSS を日頃触ってる人には常識ではあると思うのだが、少なくとも僕は CSS に真面目に入門するまではどういうことが起きているのかまるで分からなかった。今回は、この CSS を触ってる人には常識であろう、しかし CSS を使い慣れていない人には知らない人も多いと思われる CSS レイアウトの基本について見ていこうと思う。</p>
<div class="section" id="auto-id-1">
<h2>通常フロー<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>「<a class="reference external" href="https://developer.mozilla.org/ja/docs/Learn/CSS/CSS_layout/Introduction">CSS レイアウト入門 | MDN</a>」という素晴らしい入門サイトがあるので、そっち見てもらった方がいいかもしれんが、ひとまず基本から。</p>
<p>Web コンテンツは、コンテンツ内容を表す構造化データ HTML、そしてその構造化データの見た目、つまり配置と装飾を司る CSS で基本的に構成されている。JavaScript やその他の Web API により、ブラウザ上でコンテンツを動的に弄る術も発展しており、昨今は JavaScript から動的にコンテンツ生成する技法が主流になりつつはあるが、そこでも基本的にはコンテンツデータを HTML 片で、配置と装飾は CSS 片でが主流である。CSS というと装飾機能というイメージを持つ人は多いかもしれないが、Web コンテンツとしてはコンテンツ配置も CSS に分離されている。単に HTML 要素に対してデフォルトの配置が決まっているだけで、やろうと思えば自由に配置を弄れる。</p>
<p>CSS において配置を制御する最も基本的な方法が、 <tt class="docutils literal">display</tt> プロパティによるページレイアウトである。 <tt class="docutils literal">display</tt> プロパティは HTML 要素に対して、大きく2種類のレイアウト設定を行える:</p>
<dl class="docutils">
<dt>通常フローでの要素の振る舞い (display-outside)</dt>
<dd>レイアウト方法はいくつか種類があるが、その内通常フロー (normal flow)、またはフローレイアウトと呼ばれるデフォルトで採用されるレイアウト上で、その要素がどう振る舞うかを指定する。</dd>
<dt>内側でのレイアウト方法 (display-inside)</dt>
<dd>その要素の子要素に対してどういうレイアウト方法を適用するかを指定する。</dd>
</dl>
<p>正確には他にもいくつかの設定を指定可能だが、そこは今回は触れない。display-outside には、後述する <tt class="docutils literal">block</tt>、 <tt class="docutils literal">inline</tt> の2種類が指定できる。また、display-inside にはフローレイアウト <tt class="docutils literal">flow</tt> の他いくつかのレイアウト方法を指定できるが、ひとまず <tt class="docutils literal">flow</tt> のみ見ていく。これら2つを組み合わせて、例えば display-outside <tt class="docutils literal">block</tt>、display-inside <tt class="docutils literal">flow</tt> の場合 <tt class="docutils literal">display: block flow;</tt> のように指定する。</p>
<p>さて、CSS のレイアウトは基本的には何種類かのボックスを要素ごとに発行し、それぞれのボックスのコンテキストに従って配置を決めていく。フローレイアウトにおいては、基本的には、 <tt class="docutils literal">block</tt> は垂直方向への配置、 <tt class="docutils literal">inline</tt> は水平方向への配置を行う指定になる。では、その詳細を見ていこう。</p>
<p>まず、 <tt class="docutils literal">display: block flow;</tt> が指定された要素は、ブロックボックスというボックスを発行する。ブロックボックスは、CSS 上でブロックレベルボックスと呼称されるものの性質を持ち、かつブロックコンテナボックスと呼ばれる性質も持つもののことだ。ブロックレベルボックスの性質として、コンテナボックス内に配置されると水平方向に伸びスペースを占有する。また、ブロックコンテナボックスの性質から、中に複数のブロックレベルボックスまたは複数のインラインレベルボックスを配置できる。つまり、その要素の外側、親要素から見た時の性質としては水平方向のスペースを占有して垂直方向に配置されるボックスとして振る舞い、要素の内側に配置される子要素からは垂直もしくは水平方向への要素配置空間を提供するボックスとして振る舞うということになる。</p>
<p>具体例を見る前に <tt class="docutils literal">display: inline flow;</tt> の方も見ておこう。こちらの場合はインラインボックスというボックスを発行する。インラインボックスは、インラインレベルボックスというものの性質を持ち、かつ内側の配置方法もインライン形式を取るものになる。インラインレベルボックスの性質から、水平方向にボックスが配置される。また、インライン形式での配置により、中の要素はさらに行ボックスというものに分割される。分割は要素が水平方向になるべくはみ出ないかつ、いっぱいいっぱいになるように行われ <a class="footnote-reference" href="#split-line-boxes" id="auto-id-2">[1]</a>、水平方向に収まらない行ボックスは次の行に回されることで配置が行われる。</p>
<p>なお、ブロックボックス、インラインボックスは、適宜自動で生成されることもある。例えば、次の例を見てみよう:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block flow;"</span><span class="p">></span>
この HTML 片では、
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block flow;"</span><span class="p">></span>ブロックボックス<span class="p"></</span><span class="nt">div</span><span class="p">></span>
と
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: inline flow;"</span><span class="p">></span>インラインボックス<span class="p"></</span><span class="nt">div</span><span class="p">></span>
が双方生成されます。
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div></td></tr></table></div>
<p>この場合まず、一番外側の <tt class="docutils literal">div</tt> 要素でブロックボックスが発行され、その中身がそのボックスに配置されることになる。そして、ブロックコンテナボックスの性質として、ブロックレベルボックスが一つでも含まれるブロックコンテナボックスでは、全ての要素がブロックレベルボックスに配置されるよう、自動でブロックボックスが発行される。具体的に上の例では、以下のようなブロックボックス生成が行われる:</p>
<img alt="3つの生成されたブロックボックスを可視化" src="https://mizunashi-mana.github.io/blog/posts/2023/10/display-property-of-css/display-property-of-css/force-blocks-image.png"/>
<p>この場合、「<tt class="docutils literal"><div <span class="pre">style="display:</span> block <span class="pre">flow;">ブロックボックス</div></span></tt>」がブロックレベルボックスであるため、他のテキストノードも含めた要素は、それぞれ必要に応じて自動生成されたブロックボックス内に配置される。さらに、ブロックレベルボックスを含まないブロックコンテナボックス内のテキストノードは、自動生成されたインラインボックスに配置される。これにより、次のようなインラインボックス生成が行われる:</p>
<img alt="5つの生成されたインラインボックスを可視化" src="https://mizunashi-mana.github.io/blog/posts/2023/10/display-property-of-css/display-property-of-css/generated-inline-boxes-image.png"/>
<p>もう一つ例を見ておこう。</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block flow;"</span><span class="p">></span>
水平方向に収まらない
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: inline flow;"</span><span class="p">></span>インラインレベルボックス<span class="p"></</span><span class="nt">div</span><span class="p">></span>
は、複数の
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: inline flow;"</span><span class="p">></span>行ボックス<span class="p"></</span><span class="nt">div</span><span class="p">></span>
に分割され、必要に応じて垂直方向への移動を挟みながら水平方向に並べられます。
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div></td></tr></table></div>
<p>に対して、以下のようなインラインボックス生成が行われる:</p>
<img alt="5つの生成された行ボックスを可視化" src="https://mizunashi-mana.github.io/blog/posts/2023/10/display-property-of-css/display-property-of-css/generated-inline-boxes-image-with-lines.png"/>
<p>さらに水平方向に収まらない部分は、行ボックス分割がおき、必要に応じて垂直方向への移動がおきる:</p>
<img alt="6つの生成された行ボックスを可視化" src="https://mizunashi-mana.github.io/blog/posts/2023/10/display-property-of-css/display-property-of-css/generated-line-boxes-image.png"/>
<p>これが通常フローでの配置の基本となる。</p>
</div>
<div class="section" id="html">
<h2>HTML 要素のボックスタイプ<a class="headerlink" href="#html" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、CSS のデフォルトのレイアウト方法、通常フローもしくはフローレイアウトでは、ブロックボックス、インラインボックスの発行を指定することで配置方法を制御できることは分かってもらえただろう。これにより、最初の例はある程度説明がつく。つまり、</p>
<div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">style</span><span class="p">></span>
<span class="w"> </span><span class="nt">div</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">display</span><span class="p">:</span><span class="w"> </span><span class="kc">block</span><span class="w"> </span><span class="k">flow</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nt">span</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">display</span><span class="p">:</span><span class="w"> </span><span class="kc">inline</span><span class="w"> </span><span class="k">flow</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p"></</span><span class="nt">style</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span><span class="p">></span>デザインにおいて、<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"text-decoration: underline;"</span><span class="p">></span>レイアウト<span class="p"></</span><span class="nt">div</span><span class="p">></span>は重要な要素だ。<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span><span class="p">></span>デザインにおいて、<span class="p"><</span><span class="nt">span</span> <span class="na">style</span><span class="o">=</span><span class="s">"text-decoration: underline;"</span><span class="p">></span>レイアウト<span class="p"></</span><span class="nt">span</span><span class="p">></span>は重要な要素だ。<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div>
<p>という解釈が行われる仕組みがあれば、 <tt class="docutils literal">div</tt> タグを使った場合と <tt class="docutils literal">span</tt> タグを使った場合のレイアウトの違いについて説明がつく。実はまさに、HTML Standard と CSS3 の CSS デフォルト値から、以上の挙動と同じになることが説明できる。</p>
<p>まず、CSS3 では <tt class="docutils literal">display</tt> プロパティの初期値は、 <tt class="docutils literal">inline</tt> となることが決められている <a class="footnote-reference" href="#spec-of-display-property" id="auto-id-3">[2]</a>。つまり、通常明示的に <tt class="docutils literal">display</tt> プロパティを書かない場合、 <tt class="docutils literal">display: inline;</tt> と書くのと同じ挙動になることになる。 <tt class="docutils literal">display: inline;</tt> は詳細は後述するが、 <tt class="docutils literal">display: inline flow;</tt> の省略形となる。よって上の例は、 <tt class="docutils literal">span</tt> についてはわざわざ <tt class="docutils literal">display: inline flow;</tt> と指定しなくても良いことになる。また、HTML Standard には HTML 要素に対するデフォルトのスタイルシートが規定されており <a class="footnote-reference" href="#spec-of-html-rendering" id="auto-id-4">[3]</a>、以下の要素はデフォルトで <tt class="docutils literal">display: block;</tt> が指定されている:</p>
<ul class="simple">
<li><tt class="docutils literal">html</tt></li>
<li><tt class="docutils literal">body</tt></li>
<li><tt class="docutils literal">address</tt></li>
<li><tt class="docutils literal">blockquote</tt></li>
<li><tt class="docutils literal">center</tt></li>
<li><tt class="docutils literal">dialog</tt></li>
<li><tt class="docutils literal">div</tt></li>
<li><tt class="docutils literal">figure</tt></li>
<li><tt class="docutils literal">figcaption</tt></li>
<li><tt class="docutils literal">footer</tt></li>
<li><tt class="docutils literal">form</tt></li>
<li><tt class="docutils literal">header</tt></li>
<li><tt class="docutils literal">hr</tt></li>
<li><tt class="docutils literal">legend</tt></li>
<li><tt class="docutils literal">listing</tt></li>
<li><tt class="docutils literal">main</tt></li>
<li><tt class="docutils literal">p</tt></li>
<li><tt class="docutils literal">plaintext</tt></li>
<li><tt class="docutils literal">pre</tt></li>
<li><tt class="docutils literal">search</tt></li>
<li><tt class="docutils literal">xmp</tt></li>
</ul>
<p><tt class="docutils literal">display: block;</tt> は <tt class="docutils literal">display: block flow;</tt> と書くのと同じ挙動になる。これらの仕様から最初に提示した振る舞いが起きることになる。</p>
</div>
<div class="section" id="auto-id-5">
<h2>その他のレイアウト<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>最後に、<tt class="docutils literal">display</tt> プロパティについてもう少し詳細を見ておこう。display-outside についてはもう見たわけだが、display-inside は <tt class="docutils literal">flow</tt> の他にいくつかレイアウト方法を指定できる。他に指定できる種類は以下だ:</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">flow-root</span></tt></dt>
<dd>ブロックコンテナボックスを、独自の配置空間で発行し、そこに子要素を配置する。<tt class="docutils literal">flow</tt> と異なるところは、例え display-outside で <tt class="docutils literal">inline</tt> が指定されていようとブロックコンテナボックスが発行されるところだ。</dd>
<dt><tt class="docutils literal">flex</tt></dt>
<dd>フレックスボックスという特殊なボックスを発行し、独自のレイアウト方法を取る。詳しくは、<a class="reference external" href="https://developer.mozilla.org/ja/docs/Learn/CSS/CSS_layout/Flexbox">フレックスボックス入門ガイド</a> を見てもらうのが良いだろう。</dd>
<dt><tt class="docutils literal">grid</tt></dt>
<dd>グリッドボックスという特殊なボックスを発行し、独自のレイアウト方法を取る。詳しくは、<a class="reference external" href="https://developer.mozilla.org/ja/docs/Learn/CSS/CSS_layout/Grids">グリッド入門ガイド</a> を見てもらうのが良いだろう。</dd>
<dt><tt class="docutils literal">table</tt></dt>
<dd><tt class="docutils literal">table</tt> タグと同様のレイアウトを取る。これは今回は詳しくは触れない。中々使う機会もないだろう。</dd>
<dt><tt class="docutils literal">ruby</tt></dt>
<dd><tt class="docutils literal">ruby</tt> タグと同様のレイアウトをとる。これは今回は詳しくは触れない。中々使う機会もないだろう。</dd>
</dl>
<p>これらと display-outside の組み合わせで <tt class="docutils literal">display</tt> プロパティを指定する。なお、CSS2 との互換性と省略のため、省略形が規定されている。それぞれ次のようになる:</p>
<table border="1" class="docutils">
<colgroup>
<col width="50%"/>
<col width="50%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">省略形</th>
<th class="head">新しい値</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>display: inside;</td>
<td>display: inside flow;</td>
</tr>
<tr><td>display: block;</td>
<td>display: block flow;</td>
</tr>
<tr><td>display: flow-root;</td>
<td>display: block flow-root;</td>
</tr>
<tr><td>display: inline-block;</td>
<td>display: inline flow-root;</td>
</tr>
<tr><td>display: flex;</td>
<td>display: block flex;</td>
</tr>
<tr><td>display: inline-flex;</td>
<td>display: inline flex;</td>
</tr>
<tr><td>display: grid;</td>
<td>display: block grid;</td>
</tr>
<tr><td>display: inline-grid;</td>
<td>display: inline grid;</td>
</tr>
<tr><td>display: ruby;</td>
<td>display: inline ruby;</td>
</tr>
<tr><td>display: table;</td>
<td>display: block table;</td>
</tr>
<tr><td>display: inline-table;</td>
<td>display: inline table;</td>
</tr>
</tbody>
</table>
<p>特に <tt class="docutils literal"><span class="pre">inline-block</span></tt>、つまり <tt class="docutils literal">inline <span class="pre">flow-root</span></tt> は通常フローでも重宝される <tt class="docutils literal">display</tt> 指定で、例えば次のような配置を実現できる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block flow;"</span><span class="p">></span>
インラインブロックを使用することで、
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: inline flow-root;"</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block;"</span><span class="p">></span>ブロック1<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block;"</span><span class="p">></span>ブロック2<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
のようにインラインレベルでブロックを二重に並べたりできます。
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div></td></tr></table></div>
<img alt="インラインボックスによる配置" src="https://mizunashi-mana.github.io/blog/posts/2023/10/display-property-of-css/display-property-of-css/inline-block-image.png"/>
<p>単純にインラインボックスの中にブロックボックスを配置する、つまり</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block flow;"</span><span class="p">></span>
インラインブロックを使用することで、
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: inline flow;"</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block flow;"</span><span class="p">></span>ブロック1<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"><</span><span class="nt">div</span> <span class="na">style</span><span class="o">=</span><span class="s">"display: block flow;"</span><span class="p">></span>ブロック2<span class="p"></</span><span class="nt">div</span><span class="p">></span>
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
のようにインラインレベルでブロックを二重に並べたりできます。
<span class="p"></</span><span class="nt">div</span><span class="p">></span>
</pre></div></td></tr></table></div>
<p>というような書き方では、内部のブロックは横一杯に広がってしまう。しかし、 <tt class="docutils literal">inline <span class="pre">flow-root</span></tt> では独自の配置空間を作ることにより、外側から見たらインラインレベルボックスとして、内側から見たらブロックコンテナボックスとして振る舞えるようになる。つまり、その行の部分的な要素でありながら、内部にボックスを配置できるような振る舞いを持たせることができる。この辺の詳細を正確に知りたい場合は、CSS2 の幅・高さ計算などの仕様を見てもらうのがいいだろう。なお、 <tt class="docutils literal">inline <span class="pre">flow-root</span></tt> をデフォルトの挙動として持つ HTML 要素として、</p>
<ul class="simple">
<li><tt class="docutils literal">input</tt></li>
<li><tt class="docutils literal">button</tt></li>
</ul>
<p>がある。これらの振る舞いの違いやデフォルト値によって、現在の HTML の Web ブラウザでの描画配置は形作られている。</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで今回は、CSS の基礎ではあるが、日頃触ってない人にはあまり知られていない通常フローの配置について紹介した。通常フローでは、ブロックボックスとインラインボックスという基本的なレイアウト要素がある。また、それぞれの区分けは HTML 要素ごとにデフォルト値が決まっており、明示的に指定しない場合はその HTML の意味論に沿った配置がされる。あくまでデフォルト配置なので、配置のために HTML の意味論に反した使い方をするより、HTML の意味論に沿った使い方をしつつ明示的に配置方法を CSS で変更するのがいいだろうが、デフォルトの挙動を把握することは HTML の意味論の理解にも繋がりやすいだろう。</p>
<p>実はここら辺のレイアウトがちゃんと HTML / CSS で切り離されたのは結構最近だったりするし、CSS3 の <tt class="docutils literal">display</tt> 2値指定も取り扱ってる文献はまだまだ少ない。なので、それらを整理して理解する良い機会となった。ま、何かの参考になれば嬉しい。では、今回はこれで。</p>
<table class="docutils footnote" frame="void" id="split-line-boxes" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><tt class="docutils literal"><span class="pre">word-break</span></tt> プロパティなどにより、ある程度分割の戦略は制御できる。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="spec-of-display-property" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[2]</a></td><td><a class="reference external" href="https://www.w3.org/TR/css-display-3/#propdef-display">https://www.w3.org/TR/css-display-3/#propdef-display</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="spec-of-html-rendering" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[3]</a></td><td><a class="reference external" href="https://html.spec.whatwg.org/multipage/rendering.html#rendering">https://html.spec.whatwg.org/multipage/rendering.html#rendering</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/10/display-property-of-css.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/10/display-property-of-css.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>アーカイブ済み ActivityPub サーバの実装2023-09-09T09:06:22+09:002023-09-09T09:06:22+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-09-09:/blog/posts/2023/09/archived-activitypub-server/<p>Fediverse は ActivityPub をしゃべるサーバを基本単位とした分散型 SNS ネットワークである。ActivityPub は W3C が勧告する分散型 SNS の標準プロト …</p><p>Fediverse は ActivityPub をしゃべるサーバを基本単位とした分散型 SNS ネットワークである。ActivityPub は W3C が勧告する分散型 SNS の標準プロトコルで、ActivityStreams というデータフォーマットプロトコルを元に、SNS 上のコンテンツを HTTP 上で JSON を通してやり取りする通信方法を規定する。サーバ実装も多様化しているが、基本的には ActivityStreams の方に拡張を加えた ActivitiyPub と、WebFinger と呼ばれるアカウントに対して紐づけるリソース URL を HTTP で発信するプロトコルへの対応、そしてクライアント用 API を用意しているものが多い。</p>
<p>さて、分散型 SNS は変化が早く、各サーバの寿命も短い傾向にある。運営の完全撤退の場合もあるが、サーバソフトウェアの変更や、並走して動かしていたサーバをどちらかに統一したい場合など、管理上の都合で一部サーバを停止することもよくある。しかしそうなった場合、リンク先が機能しなくなり引用文献などが参照できなくなる他、ユーザIDから情報が辿れなくなってしまい参照性が失われやすい。</p>
<p>丁度、僕も Mastodon から Firefish というソフトウェアへの移行を目指しており、最近、幾つか Fediverse インスタンスのアーカイブ方法について研究してみていた。今回は Fediverse の技術的な概要と研究した内容について紹介したいと思う。</p>
<div class="section" id="fediverse">
<h2>Fediverse を支えるプロトコル<a class="headerlink" href="#fediverse" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Fediverse で基本となるプロトコルは、ActivityPub と呼ばれるものである。ActivityPub では、actor と呼ばれるリソースから activity と呼ばれるメッセージを配信したり、逆に actor が activity を受信することで、Fediverse 上のコンテンツをやり取りする。actor はメッセージ受信用リソース inbox とメッセージ送信用リソース outbox を持っており、これらのリソースから HTTP GET メソッドでメッセージを取得、POST メソッドでメッセージを送信する。 <a class="reference external" href="https://www.w3.org/TR/activitypub/">W3C の ActivityPub recommendation</a> から図を借りると、</p>
<img alt="ActivityPub チュートリアル" src="https://mizunashi-mana.github.io/blog/posts/2023/09/archived-activitypub-server/archived-activitypub-server/activitypub-tutorial-2.png"/>
<p>のようなイメージとなる。</p>
<p>例えば、Mastodon の公式アカウントの actor リソースは、 <a class="reference external" href="https://mastodon.social/users/Mastodon">https://mastodon.social/users/Mastodon</a> という URI に置かれている。アクセスするには、</p>
<pre class="literal-block">
$ curl -qsSL 'https://mastodon.social/users/mastodon' -H 'Accept: application/activity+json' | jq
{
"@context": [
"https://www.w3.org/ns/activitystreams",
..
],
"id": "https://mastodon.social/users/Mastodon",
"type": "Person",
"following": "https://mastodon.social/users/Mastodon/following",
"followers": "https://mastodon.social/users/Mastodon/followers",
"inbox": "https://mastodon.social/users/Mastodon/inbox",
"outbox": "https://mastodon.social/users/Mastodon/outbox",
"featured": "https://mastodon.social/users/Mastodon/collections/featured",
"featuredTags": "https://mastodon.social/users/Mastodon/collections/tags",
"preferredUsername": "Mastodon",
"name": "Mastodon",
"summary": "<p>Free, open-source decentralized social media platform.</p>",
"url": "https://mastodon.social/@Mastodon",
...
}
</pre>
<p>のように、 <tt class="docutils literal">Accept</tt> ヘッダに <tt class="docutils literal">application/activity+json</tt> をつけて HTTP GET メソッドでアクセスを行う必要がある。このように、ActivityPub では基本的に <a class="reference external" href="https://www.w3.org/TR/json-ld/">JSON-LD</a> と呼ばれる JSON 形式の上で構造化データを表現する形式を採用しており、MIMEタイプ <tt class="docutils literal">application/activity+json</tt> のデータとして Web 上でやり取りを行う。ただ、ActivityPub 自体はそのデータをどうやり取りするかを主に定義しており、データの意味論や形式の標準は <a class="reference external" href="https://www.w3.org/TR/activitystreams-core/">ActivityStreams</a> に切り出されている。actor リソースが持つ基本的な情報は、以下の通り:</p>
<dl class="docutils">
<dt>inbox リソース</dt>
<dd>inbox リソースは actor が受け取った activity のコレクションを表すリソース。ActivityPub では、actor の <tt class="docutils literal">inbox</tt> フィールドにその URI が指定されているのが基本的な制約になる。inbox リソースはクライアント向けに GET メソッドでアクセスされると activity コレクションを返し、連合サーバからは POST メソッドで activity を受け取るようになっている必要がある。ただ、GET メソッドの方は対応してるソフトはあんまりないが。なお、連合を拒否するには POST に対して 405 を返すのがいいらしい <a class="footnote-reference" href="#activitypub-inbox-delivery" id="auto-id-1">[1]</a>。</dd>
<dt>outbox リソース</dt>
<dd>outbox リソースは actor が発信してる activity のコレクションを表すリソース。ActivityPub では、actor の <tt class="docutils literal">outbox</tt> フィールドにその URI が指定されているのが基本的な制約になる。outbox リソースは連合サーバ向けに GET メソッドでアクセスされると activity コレクションを返し、クライアントからは POST メソッドで配信する activity を受け取るようになっている必要がある。ただ、こちらはあまり実際に使ってるソフトはいなくて対応状況も悪い。まあ、GET メソッドの方は大体対応している気はするが。</dd>
<dt>followers リソース</dt>
<dd>該当の actor をフォローしている actor のコレクションを表すリソース。ActivityPub では、actor の <tt class="docutils literal">followers</tt> フィールドにその URI が指定されているのが基本的な制約になる。</dd>
<dt>following リソース</dt>
<dd>該当の actor がフォローしている actor のコレクションを表すリソース。ActivityPub では、actor の <tt class="docutils literal">following</tt> フィールドにその URI が指定されているのが基本的な制約になる。</dd>
</dl>
<p>他にも作成日、名前、アイコン画像などが載せられるが、まあその辺の詳細は <a class="reference external" href="https://www.w3.org/TR/activitystreams-core/#actors">ActivityStreams の規格</a> を覗いてもらうのがいいだろう。他に、Mastodon や Misskey などの各ソフトウェアで独自の拡張も加えていたりする。例えば、Mastodon にはディレクトリ掲載の可否を示す <tt class="docutils literal">discoverable</tt> というフラグを追加していたり、Misskey では猫かどうかを示す <tt class="docutils literal">isCat</tt> というフラグが追加されていたりする。Mastodon の拡張は <a class="reference external" href="https://docs.joinmastodon.org/spec/activitypub/">https://docs.joinmastodon.org/spec/activitypub/</a> に、Misskey の拡張は <a class="reference external" href="https://misskey-hub.net/ns.html">https://misskey-hub.net/ns.html</a> にそれぞれ記載されているので、参考にしてみるのがいいだろう。</p>
<p>この actor が持っている inbox、outbox にデータを送り合うことで、Fediverse 上でのコンテンツ共有が行われる。基本的には、連合してるサーバ同士で発信するデータを互いに送信先に inbox に POST で突っ込むのが通例だ。なお、あまり使われてなさそうだが、outbox リソースを定期的に監視することでもデータを追えはする。なので実は ActivityPub では push 型、つまり送信したいデータを送信先に投入するだけでなく、pull 型、受信側が送信元を定期的に監視することでもデータを受信できる。この際配信される情報は2つある。1つはコンテンツそのもの、もう1つがそのコンテンツに対する操作、例えばコンテンツ作成や編集、削除などである。この2つを合わせたものが activity と呼ばれ、この activity をやり取りすることでコンテンツ共有が行われる。例えば、Mastodon iOS アプリがリリースされた旨の投稿作成 activity を見てみると、</p>
<pre class="literal-block">
$ curl -qsSL 'https://mastodon.social/users/Mastodon/statuses/109831774267343989/activity' | jq
{
"@context": [
"https://www.w3.org/ns/activitystreams",
...
],
"id": "https://mastodon.social/users/Mastodon/statuses/109831774267343989/activity",
"type": "Create",
"actor": "https://mastodon.social/users/Mastodon",
"published": "2023-02-08T23:44:35Z",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://mastodon.social/users/Mastodon/followers"
],
"object": {
"id": "https://mastodon.social/users/Mastodon/statuses/109831774267343989",
"type": "Note",
"summary": null,
"inReplyTo": null,
"published": "2023-02-08T23:44:35Z",
"url": "https://mastodon.social/@Mastodon/109831774267343989",
...
"content": "<p>Today we&#39;ve released a new update to our iOS app! It brings an improved sign-up flow, home screen widgets, and many accessibility improvements.</p><p><a href=\"https://apps.apple.com/us/app/mastodon-for-iphone-and-ipad/id1571998974\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" translate=\"no\"><span class=\"invisible\">https://</span><span class=\"ellipsis\">apps.apple.com/us/app/mastodon</span><span class=\"invisible\">-for-iphone-and-ipad/id1571998974</span></a></p>",
...
}
}
</pre>
<p>といった感じだ。activity リソースが持つ基本的な情報は、以下:</p>
<dl class="docutils">
<dt>種別</dt>
<dd><tt class="docutils literal">Create</tt>、 <tt class="docutils literal">Update</tt>、 <tt class="docutils literal">Delete</tt>、 <tt class="docutils literal">Follow</tt> などのコンテンツに対する操作の種別。activity の <tt class="docutils literal">type</tt> フィールドに指定する。</dd>
<dt>コンテンツ</dt>
<dd>操作対象のオブジェクト。 <tt class="docutils literal">Note</tt>、 <tt class="docutils literal">Image</tt>、 <tt class="docutils literal">Audio</tt> など色々な種別を持つ。activity の <tt class="docutils literal">object</tt> フィールドに指定する。</dd>
<dt>配信先</dt>
<dd>activity の配信先。actor のリソース URI を指定できる他、<a class="reference external" href="https://www.w3.org/ns/activitystreams#Public">https://www.w3.org/ns/activitystreams#Public</a> のような特別な配信先の URI などが指定できる。配信形式によって activity の <tt class="docutils literal">to</tt>、 <tt class="docutils literal">bto</tt>、 <tt class="docutils literal">cc</tt>、 <tt class="docutils literal">bcc</tt>、 <tt class="docutils literal">audience</tt> フィールドに指定する。</dd>
</dl>
<p>こんな感じの情報を Fediverse では送り合ってるわけだ。まあ、送受信はもう少し色々面倒があるんだが、今回はそこには立ち入らない。</p>
<p>さて、このように actor リソースを中心に、ActivityPub は回ってる。ただ、問題はこの actor リソースの場所を共有する方法である。URI を直接共有してもいいが、Fediverse ではアカウント ID を別途発行し、それを元に actor リソースを特定する方法が取られている。これは、アカウントリソースを ActivityPub 前提にしないためだろう。このアカウント ID から actor リソースの特定方法を提供するプロトコルが WebFinger と呼ばれるものになる。WebFinger は、 <tt class="docutils literal"><span class="pre">/.well-known/webfinger</span></tt> という URI に、クエリパラメータ付きで HTTP GET アクセスをすると、そのパラメータにあったリソース URI を JSON 形式で返してくるという割と単純なもの。例えば、 <tt class="docutils literal">@Mastodon@mastodon.social</tt> のリソースをクエリするには、</p>
<pre class="literal-block">
$ curl 'https://mastodon.social/.well-known/webfinger?resource=acct:Mastodon@mastodon.social'
{
"subject": "acct:Mastodon@mastodon.social",
"aliases": [
"https://mastodon.social/@Mastodon",
"https://mastodon.social/users/Mastodon"
],
"links": [
{
"rel": "http://webfinger.net/rel/profile-page",
"type": "text/html",
"href": "https://mastodon.social/@Mastodon"
},
{
"rel": "self",
"type": "application/activity+json",
"href": "https://mastodon.social/users/Mastodon"
},
{
"rel": "http://ostatus.org/schema/1.0/subscribe",
"template": "https://mastodon.social/authorize_interaction?uri={uri}"
},
{
"rel": "http://webfinger.net/rel/avatar",
"type": "image/png",
"href": "https://files.mastodon.social/accounts/avatars/000/013/179/original/b4ceb19c9c54ec7e.png"
}
]
}
</pre>
<p>のようにする。WebFinger では</p>
<dl class="docutils">
<dt><tt class="docutils literal">resource</tt></dt>
<dd>WebFinger リソースの URI。Fediverse では、 <a class="reference external" href="https://datatracker.ietf.org/doc/html/rfc7565">acct URI スキーム</a> が使われることが多い。actor リソース URI を直接使える実装も多い。</dd>
<dt><tt class="docutils literal">rel</tt></dt>
<dd>オプションで、リソース URI の制限を指定できる。</dd>
</dl>
<p>のパラメータを受け取り、MIMEタイプ <tt class="docutils literal">application/jrd+json</tt> の JSON データを返す。レスポンスは cross origin でも受け付けられるよう、 <tt class="docutils literal"><span class="pre">Access-Control-Allow-Origin:</span> *</tt> をつけることが要求されていて、</p>
<dl class="docutils">
<dt><tt class="docutils literal">subject</tt></dt>
<dd>WebFinger リソースの一意な URI。Fediverse では基本 <a class="reference external" href="https://datatracker.ietf.org/doc/html/rfc7565">acct URI スキーム</a> が使われる。</dd>
<dt><tt class="docutils literal">aliases</tt></dt>
<dd>オプションで指定される、他にリソースを特定するために使える URI。</dd>
<dt><tt class="docutils literal">properties</tt></dt>
<dd>オプションで指定される、付加情報。</dd>
<dt><tt class="docutils literal">links</tt></dt>
<dd>WebFinger リソースに紐づくリソースへのリンク。Fediverse では、HTML リソース、ActivityPub actor リソース、OStatus と呼ばれる ActivityPub の前身の購読リソース、アバター画像のリソースなどがリンクされてることが多い。</dd>
</dl>
<p>などが返ってくる。この WebFinger は各 ActivityPub 実装に付随している。Fediverse 上の UI では、アカウント ID のドメインに対してクエリがかけられ、上記情報から actor リソースを特定し、actor リソースからアカウント情報を引っ張ってくるという感じになる。</p>
</div>
<div class="section" id="auto-id-4">
<h2>静的な ActivityPub サーバ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、ActivityPub のコンテンツ共有を除き、WebFinger から actor リソースの特定を行うまでは、単純な GET メソッドの連鎖によって行うことができる。実際、Mastodon や Misskey などに、擬似的にアカウントを作って認識させるだけなら、静的なサイトで十分可能だ。もちろん、これだと POST メソッドで inbox に activity を投入することなどはできないため、コンテンツ配信はできないが、逆に言えばコンテンツ配信しないサーバ、例えばアーカイブ済みのサーバを建てることはできる。これによりバックエンドをオブジェクトストレージにすることなども視野に入れることができ、サーバ運営の費用と手間を抑えることも期待できる。</p>
<p>ま、実際に見てみるのが早いと思うので、Cloudflare Pages でちょっと規格から外れる部分はあるが、Mastodon や Misskey で問題なく認識される擬似的な ActivityPub サーバを立ててみる。この擬似的なサーバはアカウントを一つしか持つことができない。これは、WebFinger がクエリパラメータによりリソースを認識するという問題によるものだ。ここに関してはリダイレクタを挟むなり、今回のようにクエリパラメータガン無視で一意なリソースを返すなどの工夫をする必要がある。その制約さえ許容すれば Cloudflare Pages で擬似的なサーバを立てられる。</p>
<p>まず、特別なリソースをいくつか用意しておく:</p>
<pre class="literal-block">
$ cat static/empty-collection.json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://virtual-ap-demo-mizunashi-work.pages.dev/static/empty-collection.json",
"type": "Collection",
"totalItems": 0,
"items": []
}
$ cat static/empty-ordered-collection.json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://virtual-ap-demo-mizunashi-work.pages.dev/static/empty-ordered-collection.json",
"type": "OrderedCollection",
"totalItems": 0,
"orderedItems": []
}
</pre>
<p>これは空のコレクションを表すリソース。とりあえず、 actor が認識されればいいので、 <tt class="docutils literal">inbox</tt>、 <tt class="docutils literal">outbox</tt>、 <tt class="docutils literal">following</tt>、 <tt class="docutils literal">followers</tt> など ActivityPub で必要とされるコレクションリソースには適宜上記のリソースを埋めておく。その為のもの。今回は、 <tt class="docutils literal"><span class="pre">virtual-ap-demo-mizunashi-work</span></tt> というプロジェクト名で Cloudflare Pages にプロジェクトを作ったので、それに合わせた <tt class="docutils literal">id</tt> を指定する。その辺は試す環境に合わせて変えるのがいいだろう。次にこれを元に actor リソースを作る:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"@context"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"https://www.w3.org/ns/activitystreams"</span><span class="p">,</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"manuallyApprovesFollowers"</span><span class="p">:</span><span class="w"> </span><span class="s2">"as:manuallyApprovesFollowers"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"alsoKnownAs"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"@id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"as:alsoKnownAs"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"@type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"@id"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"movedTo"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"@id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"as:movedTo"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"@type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"@id"</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"toot"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://joinmastodon.org/ns#"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"featured"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"@id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"toot:featured"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"@type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"@id"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"featuredTags"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"@id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"toot:featuredTags"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"@type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"@id"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"discoverable"</span><span class="p">:</span><span class="w"> </span><span class="s2">"toot:discoverable"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"devices"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"@type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"@id"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"@id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"toot:devices"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">"suspended"</span><span class="p">:</span><span class="w"> </span><span class="s2">"toot:suspended"</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/users/virtual-acct.json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Person"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"following"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/empty-ordered-collection.json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"followers"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/empty-ordered-collection.json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"inbox"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/not-found.json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"outbox"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/empty-ordered-collection.json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"featured"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/empty-ordered-collection.json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"featuredTags"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/empty-collection.json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"preferredUsername"</span><span class="p">:</span><span class="w"> </span><span class="s2">"virtual-acct"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Virtual User"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"summary"</span><span class="p">:</span><span class="w"> </span><span class="s2">"A virtual user of @mizunashi_mana@mstdn.mizunashi.work. Anyone cannot follow me."</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/index.html"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"manuallyApprovesFollowers"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"discoverable"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"published"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2023-08-07T00:00:00Z"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"devices"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/empty-collection.json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"movedTo"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://mstdn.mizunashi.work/users/mizunashi_mana"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"tag"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span>
<span class="w"> </span><span class="nt">"attachment"</span><span class="p">:</span><span class="w"> </span><span class="p">[]</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>これを <tt class="docutils literal"><span class="pre">static/users/virtual-acct.json</span></tt> においておく。さらに、 <tt class="docutils literal"><span class="pre">.well-known/webfinger</span></tt> に、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"subject"</span><span class="p">:</span><span class="w"> </span><span class="s2">"acct:virtual-acct@virtual-ap-demo-mizunashi-work.pages.dev"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"aliases"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/index.html"</span><span class="p">,</span>
<span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/users/virtual-acct.json"</span>
<span class="w"> </span><span class="p">],</span>
<span class="w"> </span><span class="nt">"links"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"rel"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://webfinger.net/rel/profile-page"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"text/html"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"href"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/index.html"</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">"rel"</span><span class="p">:</span><span class="w"> </span><span class="s2">"self"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"application/activity+json"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"href"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://virtual-ap-demo-mizunashi-work.pages.dev/static/users/virtual-acct.json"</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>という JSON ファイルをおく。後は、 <tt class="docutils literal">index.html</tt> を内容適当で作っておいておき、GitHub にアップして、Cloudflare Pages の GitHub connector で接続してプロジェクトを作って <tt class="docutils literal"><span class="pre">@virtual-acct@virtual-ap-demo-mizunashi-work.pages.dev</span></tt> で検索すると、 <tt class="docutils literal">@mizunashi_mana@mstdn.mizunashi.work</tt> に引越し済みのユーザを確認することができるだろう。コードの全貌は <a class="reference external" href="https://github.com/mizunashi-mana/virtual-ap-demo.mizunashi.work">https://github.com/mizunashi-mana/virtual-ap-demo.mizunashi.work</a> において実際にデプロイしてあるのでぜひ試してほしい。</p>
<p>Fediverse 上のソフトはこのアカウント ID を次の手順で辿ることが期待される:</p>
<ol class="arabic simple">
<li>まず、 <tt class="docutils literal"><span class="pre">https://virtual-ap-demo-mizunashi-work.pages.dev/.well-known/webfinger?resource=acct:virtual-ap-demo-mizunashi-work.pages.dev</span></tt> にアクセスして、WebFinger リソースを取得し、 <tt class="docutils literal">rel=self</tt> の actor リソース URI <tt class="docutils literal"><span class="pre">https://virtual-ap-demo-mizunashi-work.pages.dev/static/users/virtual-acct.json</span></tt> を入手する。</li>
<li>次に、 <tt class="docutils literal"><span class="pre">https://virtual-ap-demo-mizunashi-work.pages.dev/static/users/virtual-acct.json</span></tt> にアクセスして actor リソースを入手する。この際、適宜 <tt class="docutils literal">following</tt>、 <tt class="docutils literal">followers</tt> フィールドから空のコレクションリソースにアクセスしたり、 <tt class="docutils literal">movedTo</tt> からこの actor が引越し済みで引越し先は <tt class="docutils literal"><span class="pre">https://mstdn.mizunashi.work/users/mizunashi_mana</span></tt> であることなどを知る。</li>
<li>必要な情報を自身のデータベースに登録し、ユーザ情報を検索結果として表示する。</li>
</ol>
<p>ま、多少複雑だが、こんぐらいできれば引越し済みアカウントは別にネット世界から抹消しなくても残せるというわけだ。</p>
</div>
<div class="section" id="archivedon">
<h2>archivedon<a class="headerlink" href="#archivedon" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、上記のようにリソースをリンクだけ書き換えて単に JSON ファイル化して、いい感じに配置していけば、配信しない ActivityPub サーバは作れる。ただ、どうせなら、旧 URL からの参照性を残したり、WebFinger でマルチアカウント対応ぐらいはできるようにしておきたい。なので、そこら辺だけはうまくできるように、後アーカイブ済みリソースを閉じる予定のサーバから簡単に作れるようなソフトを Rust で書いてみた。コードは、 <a class="reference external" href="https://github.com/mizunashi-mana/archivedon">https://github.com/mizunashi-mana/archivedon</a> にある。</p>
<p>ここまでの話を踏まえれば、やってることはそこまで難しくない。このサーバ、archivedon が提供する機能は大きく3つ:</p>
<dl class="docutils">
<dt>static リソースファイルのサービング</dt>
<dd>これは単純に指定のデータディレクトリの <tt class="docutils literal">./static</tt> をそのままサーブするだけ。ここだけ、どっかのオブジェクトストレージでサービングさせることも可能。内容をどう配置するかは後述する。</dd>
<dt>WebFinger、nodeinfo などの情報生成</dt>
<dd>WebFinger リソースについては上記の通り。resource、rel パラメータを受け取り、いい感じの JSON を返す。内容はデータディレクトリの <tt class="docutils literal">./webfinger</tt> ディレクトリから取得する。内容をどう配置するかは後述する。後、Misskey や Firefish などのソフトでは、nodeinfo というリソースにも対応しておくと、サーバ情報をそこから取得していい感じに付加情報として表示してくれる。これも生成するようにしている。</dd>
<dt>旧 URI からのリダイレクト</dt>
<dd>指定のデータディレクトリの <tt class="docutils literal">./map</tt> ディレクトリにリダイレクト情報がある場合は、それを元にリダイレクトを行う。内容をどう配置するかは後述する。</dd>
</dl>
<p>後は、Misskey、Firefish 辺りはホームページのメタ情報などもスクレイピングしてきたりするので、トップページの HTML サービング機能などもつけている。使い方は、<a class="reference external" href="https://github.com/mizunashi-mana/archivedon/releases">https://github.com/mizunashi-mana/archivedon/releases</a> からバイナリ落としてきて、</p>
<pre class="literal-block">
archivedon serve --port 3333 --resource-dir ./resource --expose-url-base https://archivedon.mizunashi.work/
</pre>
<p>みたいな感じでいい感じに <tt class="docutils literal">resource</tt> ディレクトリ作って、いい感じにドメイン発行とかして、いい感じに downstream 設定すれば立つ。ま、静的ファイルサービングするだけの HTTP サーバなので、データベースとかもいらんし、キャッシュとかは nginx とか downstream 側でよしなにやってくれという感じ。static リソースも基本オブジェクトストレージに載せられるなら、downstream 側でそっちに振り分ければ archivedon は well known リソースのサービングとリダイレクタとしての役割だけでよくなり、さらにメンテが楽になるだろう。</p>
<p>それから、サーバがサーブするリソースを、稼働している ActivityPub サーバからスクレイプして作る機能も載せている。データベースからさらって作る方が効率は良いが、それだと結構公開リソースかどうかの判別で事故りそうだったのと、かなり実装依存になりそうだったのであえて避けた。代わりに HTTP リクエストで fetch しまくるので、リソースファイルの作成がかなり遅く、サーバ側にも負荷がかかる。あまり大規模なサーバではお勧めできない。やることは、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">"static_base_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://archivedon.mizunashi.work/static/"</span><span class="p">,</span>
<span class="w"> </span><span class="nt">"accounts"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="s2">"@mizunashi_mana@mstdn.mizunashi.work"</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>みたいな JSON ファイルを <tt class="docutils literal">input.json</tt> として作り、</p>
<pre class="literal-block">
archivedon-fetch --input input.json --output resource --fetch-outbox
</pre>
<p>みたいな感じで実行すると、 <tt class="docutils literal">accounts</tt> で指定されたアカウントIDから、WebFinger を経由して actor リソースを取得し、inbox、outbox などの諸々を空のコレクションリソースに、他も書き換えが必要なところは書き換えつつ、必要ないところはそのまま残しつつでリソースファイルを作成して <tt class="docutils literal">./resource/static</tt> 以下においたり、 <tt class="docutils literal">./resource/map</tt> にリダイレクトマップを作ったり、 <tt class="docutils literal">./resource/webfinger</tt> に WebFinger リソースを作ったりしてくれる。後、 <tt class="docutils literal"><span class="pre">--fetch-outbox</span></tt> を指定しておくと、同じ要領で outbox の activity を辿り投稿リソースなどに対しても同じようなことをしてくれる。後はまあ、修正することがあったら、単なる JSON ファイルなので手動で手を加えたりすることもできるだろうという感じ。</p>
<p>Content-Type などが多少規格から外れてる部分があるのと、WebFinger が受け取れるパラメータが acct URI にしか対応してないみたいな問題はあるが、実用上はそこまで問題ないんじゃないかなという感じ。ひとまず Mastodon、Firefish などでは認識されるよう頑張った。</p>
</div>
<div class="section" id="auto-id-5">
<h2>まとめ<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、Fediverse を支えるプロトコルの、主に情報取得部分特化での簡単な紹介と、その部分を利用して割りかし静的なアーカイブ済みサーバ専用ソフトの仕組み紹介をした。ひとまずこれ使ってアーカイブしていきつつ、Mastodon から Firefish へ完全にお引越ししようかなという感じ。</p>
<p>やっぱ完全に諸々持ち越せないのが Fediverse ではちょっと辛いな、そこはもうちょっとプロトコルレベルで考慮があっても良かったのではというのはあるが、ま認証というのは色々技術的に難しい問題なのでしょうがないね。アーカイブは notestock に頼るというのも一つの手だが、notestock が滅びる可能性は十分あるし、コードが公開されてて、割りかし自分の裁量でアーカイブ物の調整がしやすいものが欲しかったので、割と満足。後、ActivityPub の諸々についてちょっと知識がついて、解像度が上がった。これを機に、Fediverse の諸々を触ってみてもいいかなと思ったりしたが、ま時間はないですね。では、今回はこれで。</p>
<table class="docutils footnote" frame="void" id="activitypub-inbox-delivery" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td><a class="reference external" href="https://www.w3.org/TR/activitypub/#delivery">https://www.w3.org/TR/activitypub/#delivery</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/09/archived-activitypub-server.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/09/archived-activitypub-server.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>malloc と併用可能なアロケータを作る2023-09-01T03:09:26+09:002023-09-01T03:09:26+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-09-01:/blog/posts/2023/09/impl-custom-alloc-integrated-with-malloc/<p>大規模で、ユーザ入力などの外部要因により左右されるプログラムでは、動的なメモリ管理が必要になる場合が多い …</p><p>大規模で、ユーザ入力などの外部要因により左右されるプログラムでは、動的なメモリ管理が必要になる場合が多い。特に GC が普及した今日では、多くのプログラムにおいて基本的な機能と言えるだろう。このメモリ管理の機構として、多くのプログラミング言語実装では libc の <tt class="docutils literal">malloc</tt> / <tt class="docutils literal">free</tt> がデファクト的に使われている。一般に、プログラムの動的なメモリの割り当てと解放を抽象化した機構はメモリアロケータ、または単にアロケータと呼ばれる。libc malloc はその標準的なものとして、システムアロケータと呼ばれたりする。特に、ほとんどの環境では libc のデファクト標準で glibc が使われることから、glibc malloc が事実上の標準システムアロケータであると言ってよいだろう。このため、libc malloc は数多くのライブラリやプログラミング言語ランタイムで使われている。</p>
<p>さて、そんな glibc malloc だが、汎用性を重んじて作られているため、メモリ管理に少し手を加えたい場面ではパフォーマンス面とのバランスも考えると適さない場合もある。そのような場合に一からアロケータを作成したい場合もあるが、既存資産の相互運用も考えると malloc 互換の API を用意する、もしくは glibc malloc と併用可能にしたい場合もある。特に、libc が静的にリンクされる場合のことなども考えると、glibc malloc と併用可能な状況を作ることが望ましい場合がある。しかし、アロケータを glibc malloc と併用可能にするには多少テクニックが必要だ。今回は、x86 64bit Linux 環境で、glibc malloc と併用可能なアロケータを実装するテクニックについて紹介する。</p>
<div class="section" id="glibc-malloc">
<h2>glibc malloc の実装<a class="headerlink" href="#glibc-malloc" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まずは基本的なところから。さて、そもそも何気なく使われている <tt class="docutils literal">malloc</tt> / <tt class="docutils literal">free</tt> だが、この中身はどうなっているのだろう? glibc malloc の役割は、大雑把には、</p>
<dl class="docutils">
<dt>必要に応じたヒープ領域の拡張</dt>
<dd>メモリ管理で主に使われる領域を足りなくなったら必要に応じて OS に拡張してもらう。</dd>
<dt>使用可能な領域からのメモリ領域の切り出し</dt>
<dd>まだ使用していない領域を管理し、そこから要求された分を切り出して必要に応じてヘッダ情報を載せアプリケーション側に管理を委譲する。これは誤解している人が多いと思うが、一般的にアロケータの「メモリ割り当て」と呼ばれる動作は、実際の物理メモリへの新たなデータ書き込みを伴うものでないことが多い。これについては詳しくは後述するが、一般的にアロケータの役割は実際のメモリデータ管理と配置というよりは、メモリ番地の空き管理と予約に近い。予約済みのものをアプリケーション側に提供し、後はよしなに利用してくれ、利用終わったら言ってくれたら必要に応じて掃除して空室としてまた予約可能にしとくよという感じだろう。</dd>
<dt>使用終了した領域を使用可能にする</dt>
<dd>アプリケーション側から使用終了の告知があった領域を、必要に応じて後処理をし、使用可能な領域に戻す。</dd>
</dl>
<p>の3つだ。では、それぞれ少し詳しく見ていこう。</p>
<p>まず、そもそもだが、現代的なアーキテクチャと OS では仮想メモリという仕組みのサポートがある。通常私たちが触っているメモリの番地とは仮想的なものであり、実際の物理的なメモリにアクセスする際は CPU が OS の変換テーブルを使って実際の対応する物理メモリ番地に変換してからアクセスを行う。仮想メモリの番地は、物理的なメモリに必ずしもマッピングされているとは限らないし、物理的なメモリに連続して配置されているとも限らない。現代的にはページング方式という仮想メモリ領域の物理メモリへの展開方法が多くの場合採用されており、ざっくばらんによくある説明として、仮想メモリ空間をページという小さな固定サイズの単位に分解して、実際にデータ置かれてるページだけを物理メモリに連続してマッピングさせるというものだ。まあ、この辺の詳細は気が向いたらまた別に書くかもしれないが、詳細に立ち入るとそれだけで2、3個記事が書けるので、今回は大枠そんな感じの仕組みになってることさえ抑えて貰えばよいだろう。詳しく知りたければ「詳解Linuxカーネル」とかを読んでもらうのがいいんじゃないだろうか。とりあえず、このような仕組み上仮想メモリは物理メモリと同じサイズである必要はないし、使用領域を連続させる必要もない。</p>
<p>さて、ではプログラム実行時に私たちがいじっているメモリについてだが、まず Linux ではプロセス毎にそれぞれ仮想メモリ空間を作っており、その空間の中でもレイアウトを決めている。仮想メモリ空間のサイズは、アーキテクチャが扱える最大サイズが基本で、つまり 32bit アーキテクチャなら 2^32B = 4GB、64bit アーキテクチャなら 2^64B = 16EB となる <a class="footnote-reference" href="#virtual-memory-max-address" id="auto-id-1">[1]</a>。ただ、この内カーネルの使用領域があるため、実際にユーザ空間で自由に使用できるのは x86 32bit では 3GB まで <a class="footnote-reference" href="#virtual-memory-introduction-by-konsulko" id="auto-id-2">[2]</a>、x86 64bit では通常 128TB まで (一部 64PB までいけるものもある) <a class="footnote-reference" href="#virtual-memory-layout-of-x86-64" id="auto-id-3">[3]</a> となる。このユーザ空間の領域もある程度配置場所が決まっている。基本的には、まずプロセス管理用のデータや静的に確保されたデータ領域が置かれた後、それ以降が動的に管理されるメモリ領域となる。動的に管理される領域は中間に <tt class="docutils literal">mmap</tt> と呼ばれるシステムコールによるメモリマッピング領域が置かれ、それより手前がヒープ領域、それ以降がスタック領域となる。よくある図で書くと以下のようになる:</p>
<object data="https://mizunashi-mana.github.io/blog/posts/2023/09/impl-custom-alloc-integrated-with-malloc/impl-custom-alloc-integrated-with-malloc/process-user-memory-layout.svg" type="image/svg+xml">プロセスのユーザ空間メモリレイアウト配置</object>
<p>ヒープ領域は <tt class="docutils literal">sbrk</tt> というシステムコールにより program break を移動させることで使える領域が拡張され、動的なメモリオブジェクトが置かれる。スタックはサブルーチンの呼び出し時に stack pointer が移動することで拡張され、サブルーチンの制御情報が書かれる。メモリマッピング領域は <tt class="docutils literal">mmap</tt> システムコールが呼び出された時に必要に応じて拡張され、ファイルのメモリへのマッピング、もしくは動的なメモリオブジェクトがページ単位で置かれる。glibc malloc がメモリ割り当てに使うのはこの内ヒープ領域とメモリマッピング領域になる。</p>
<p>glibc malloc は大雑把には、 <tt class="docutils literal">malloc</tt> 時要求サイズに対する閾値で切り出し元の領域を変える。要求サイズが閾値以下であれば、そのサイズに合う切り出し領域をヒープ領域から見つけてきて返し、閾値より大きければ <tt class="docutils literal">mmap</tt> を使ってメモリマッピング領域にページ単位で割り当てる。ヒープ領域が足りなければ、 <tt class="docutils literal">sbrk</tt> システムコールによって program break を移動させる。 <tt class="docutils literal">mmap</tt> での割り当てはページ単位になるので、あまりにも割り当てサイズが小さいとメモリ領域を無駄に消費してしまうことになる。なので、全て <tt class="docutils literal">mmap</tt> で凌ぐのはメモリ容量が増えた現代でも割と愚策。では、逆になぜ全部ヒープ領域でやらないかだが、その前にざっくりヒープ領域の管理アルゴリズムの概要を見ていこう。</p>
<p>さて、サイズに合う切り出し領域をヒープ領域から見つけてきて返すというのは、言うのは簡単だが実際に実装する際はいくつかステップが必要だ。まず、どの領域が既に使用済みで、どこからどこまでが使用可能かを特定する必要がある。ただ、私たちは数個のレジスタに記録した情報だけからこれを探さないといけない。愚直にはこの特定作業は、使用箇所をメモっておいてその使用箇所を先頭から調べていけば良い。実際初期の glibc malloc はそんな感じのことをしていたらしい。ただ、現代はメモリはギガ単位が普通であり、メモリ割り当ての度にそんなことをしてるとプログラムの実行速度にかなり影響が出る。そこで近代では、ある程度のサイズ毎にリストを作り、そこにそのサイズ毎の空きブロックをぶら下げておきそれをメモリ割り当ての際は返し、返却されたらまたリストにぶら下げると言うことをしている。これによりわざわざ全ての使用箇所を線形探索する必要はなくなるわけだ。ただ、可能性のある全サイズでリストを作るのはそれはそれでメモリ管理的に無駄が大きい。特に再利用される可能性のあるブロックのサイズというのはある程度傾向があり、ある程度大きくなってくるとサイズはかなりばらけてくる。そこで、再利用される可能性の高いある程度小さいブロックはヒープ領域でリストに紐づけて管理し、ある程度大きいブロックは <tt class="docutils literal">mmap</tt> で OS に要求して直接取ることで両方使用可能領域の線形探索を避けることができる。またこれは断片化の回避にもつながる。単純にヒープ領域を先頭から切り出して割り当て、いらなくなったら解放といったことをやっていると、メモリの使用可能領域はかなり穴ボコ状態になって、連続した領域のサイズが限られてくる。その為、メモリの空きは 1G あるのに、1kB の連続領域はない為割り当てができないといったことになりかねない。小さいサイズのブロックの割り当て領域をある程度決めて整理した割り当てができればこのような状況を比較的回避しやすくなる。これが、ヒープ領域とメモリマッピング領域が併用されている理由になる。ここら辺の詳細は、kosaki さんの <a class="reference external" href="https://www.slideshare.net/kosaki55tea/glibc-malloc">malloc の旅</a> というスライドが大変分かりやすい。参考にすると良いだろう。</p>
</div>
<div class="section" id="mmap">
<h2>mmap と無名マッピング<a class="headerlink" href="#mmap" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、glibc malloc がヒープ領域とメモリマッピング領域を併用して動的なメモリ管理を行なってることは分かった。問題はこの glibc malloc のメモリ管理を邪魔しない形で、新たにメモリ管理機構を載せるにはどうすればいいかだ。ヒープ領域を使ってしまうと、諸に glibc malloc のメモリ管理と色々衝突してしまうことになる。今回紹介する方法は、簡単にはヒープ領域はダメでもメモリマッピング領域で <tt class="docutils literal">mmap</tt> から領域取得する分には glibc malloc の動きを阻害することがないので、 <tt class="docutils literal">mmap</tt> で独自のヒープ領域を切り出してこようというものだ。その話に入る前に、 <tt class="docutils literal">mmap</tt> の無名マッピングと呼ばれる機能についてもう少し詳しく見ておく。これは、glibc malloc の <tt class="docutils literal">mmap</tt> による領域確保でも使われている機能になる。</p>
<p><tt class="docutils literal">mmap</tt> システムコールは基本的にファイルをメモリにマッピングすることを想定して作られたシステムコールだ。有名どころで言うと、共有ライブラリの読み込みが <tt class="docutils literal">mmap</tt> により行われる。しかし、動的メモリ管理における需要を受けて、ファイルに紐づかないマッピング領域作成モード、 <tt class="docutils literal">MAP_ANONYMOUS</tt> が導入されて以来こちらもかなり色々な場面で利用されるようになっている。 <tt class="docutils literal">mmap</tt> は作成するマッピングに対して幾つかモードを指定できる。 <tt class="docutils literal">MAP_ANONYMOUS</tt>、無名モードはそのモードの中の一つだ。glibc malloc が <tt class="docutils literal">mmap</tt> でメモリ割り当てを行う際は、当然その領域はファイルには紐づかないので無名モードで領域が確保されることになる。</p>
<p><tt class="docutils literal">mmap</tt> システムコールは、以下の API を持つ <a class="footnote-reference" href="#man-of-mmap" id="auto-id-5">[4]</a>:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="nf">mmap</span><span class="p">(</span><span class="kt">void</span><span class="w"> </span><span class="n">addr</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">length</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">prot</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">flags</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">fd</span><span class="p">,</span><span class="w"> </span><span class="kt">off_t</span><span class="w"> </span><span class="n">offset</span><span class="p">);</span>
</pre></div></td></tr></table></div>
<p>一つ目の <tt class="docutils literal">addr</tt> はマッピングする領域のヒントとなるアドレスを受け取る。アドレスが <tt class="docutils literal">NULL</tt> なら適当なアドレスを持ってくるし、 <tt class="docutils literal">NULL</tt> でないならその周辺から切り出してくる。 <tt class="docutils literal">length</tt> は領域のサイズになる。 <tt class="docutils literal">prot</tt>、 <tt class="docutils literal">flags</tt> は後述する。 <tt class="docutils literal">fd</tt> は、マッピング元のファイルディスクリプタで、無名モードの場合は <tt class="docutils literal"><span class="pre">-1</span></tt> を渡す。 <tt class="docutils literal">offset</tt> はマッピング元ファイルのオフセットを指定でき、無名モードの場合は <tt class="docutils literal">0</tt> を渡す。 <tt class="docutils literal">flags</tt> では、マッピングモードのビット集合を指定する。詳細は、マニュアルを見てもらいたいが、今回扱いたいものだけ紹介しておくと、</p>
<dl class="docutils">
<dt><tt class="docutils literal">MAP_PRIVATE</tt></dt>
<dd>他プロセスと共有しないマッピング領域を、遅延書き込み (copy-on-write) で作成する。プライベートモードで作成された領域は、 <tt class="docutils literal">mmap</tt> 完了時は物理メモリには載らず、仮想メモリ上での予約のみがされた状態になる。そして、初回アクセス時ページフォールト例外を受けて初めて物理領域へのページ登録が起こる。なお、単に読み込みアクセスだけを行う場合は特殊な0埋め領域を参照するようになっており、書き込みアクセス時初めて専用の物理メモリスペースが確保される。これが遅延書き込みの機能になる。</dd>
<dt><tt class="docutils literal">MAP_ANONYMOUS</tt></dt>
<dd>無名モードを指定するフラグ。このモードの場合、ファイルには紐づかず、単なるメモリ領域として使用できる。</dd>
<dt><tt class="docutils literal">MAP_FIXED</tt></dt>
<dd><tt class="docutils literal">addr</tt> 引数で指定されたアドレスについて、ヒントではなく正確にそのアドレスを始点とする領域を確保する。ただし、 <tt class="docutils literal">addr</tt> 引数はページサイズできちんとアラインされてる必要があり、またアーキテクチャによっては他にも条件が科されることがあり移植性はあまりよくない。そのため、あまり使用は推奨されていない。</dd>
</dl>
<p>のようなフラグやその他色々が指定できる。 <tt class="docutils literal">prot</tt> はマッピング領域の保護権限を指定する。アクセス権限を与えない <tt class="docutils literal">PROT_NONE</tt>、もしくは以下による空でないビット集合を指定できる:</p>
<dl class="docutils">
<dt><tt class="docutils literal">PROT_EXEC</tt></dt>
<dd>実行可能。バッファオーバーフローなどを利用してこの領域に意図しない書き込みをされたりすると、セキュリティホールの元となるのでこの権限を設定する領域の管理には注意が必要。</dd>
<dt><tt class="docutils literal">PROT_READ</tt></dt>
<dd>読み込み可能。</dd>
<dt><tt class="docutils literal">PROT_WRITE</tt></dt>
<dd>書き込み可能。</dd>
</dl>
<p>glibc malloc では、 <tt class="docutils literal">MAP_ANONYMOUS|MAP_PRIVATE</tt> モードで、かつ <tt class="docutils literal">PROT_READ|PROT_WRITE</tt> 権限の領域確保が使われている <a class="footnote-reference" href="#glibc-sysmalloc-mmap-impl" id="auto-id-6">[5]</a>。同じように無名モードで <tt class="docutils literal">mmap</tt> で確保された領域を使えば、glibc malloc の管理機構に迷惑をかけることなく独自の動的なメモリ領域を確保できる。</p>
<p>ただ、課題もある。ヒープ領域は仮想メモリアドレスにおいては連続的であるため、それを利用したアドレス計算テクニックなどが使えるが、 <tt class="docutils literal">mmap</tt> で随時メモリ領域をメモリマッピング領域に確保していく場合、常に連続的に領域を拡張できるとは限らない。なぜなら、glibc malloc などが確保した領域が間に挟まってくるかもしれないからだ。今回紹介するのは、この問題を <tt class="docutils literal">PROT_NONE</tt> 権限でのメモリマッピングにより回避する方法だ。</p>
<p><tt class="docutils literal">PROT_NONE</tt> 権限で <tt class="docutils literal">mmap</tt> を実行すると、アクセス権限を持たないメモリマッピング領域が確保される。これは、物理メモリへの参照を持たずアクセスするとエラーが起きる一見役に立たない機能に見えるが、あることに応用ができる。それは、仮想メモリアドレスの予約である。つまり、事前に <tt class="docutils literal">PROT_NONE</tt> 権限である程度の仮想メモリ領域を <tt class="docutils literal">mmap</tt> しておけば、その仮想メモリのアドレスは使用済みとなり、それ以降の <tt class="docutils literal">mmap</tt> で使用されることはないというわけである。この予約は、 <tt class="docutils literal">munmap</tt> しない限り解除されない。また、メモリの権限は <tt class="docutils literal">mprotect</tt> システムコール、または <tt class="docutils literal">mmap</tt> 時 <tt class="docutils literal">MAP_FIXED</tt> モードを指定してそのアドレスへの上書きマッピングを行うことで更新できる。つまり、事前に <tt class="docutils literal">PROT_NONE</tt> で膨大なメモリ領域を予約しておき、その後随時必要になったら <tt class="docutils literal">mprotect</tt> で <tt class="docutils literal">PROT_READ|PROT_WRITE</tt> 権限を付与した領域を増やしていくことで、program break 移動により拡張できるヒープ領域と同じような管理を行うことができるということだ。仮想メモリは 64bit 環境であれば物理メモリより通常かなり空間が大きいので、4分の1ぐらい予約しておいても支障はほとんどない。予約しても単にアドレスが他で使えなくなるだけで物理メモリに載るわけでもないし、残りの4分の3は自由に使えるわけで、例えば 64bit だと 32TB の仮想メモリ領域を予約領域として、残りの 96TB の仮想メモリ領域を他のメモリ管理機構が自由に使える。これで問題が出るサーバは普通ないだろう。これを利用することで、新たなヒープ領域を作るメモリ管理を2重に独立した領域で作ることができるというわけだ。</p>
<p>これは実は Go 言語の 64bit 向けのランタイムで使われてる手法で、これにより cgo などで glibc malloc との共存ができるようになっている。32bit でこの方法を使うと流石に少し支障が出てしまうのが難点なのと、Linux での実装とアーキテクチャのメモリ管理機構の仕組みに強く依存しているので移植性が悪いという問題はあるが、64bit のアーキテクチャで広く流通している x86 64、ARM64 ではこの手法が使え、Windowsでも Win API で似たような機能が搭載されているため大体の範囲で適用でき、しかも既存の仕組みをあまり壊さずそこまで複雑な手段を必要とせず使える点が有用だ。</p>
</div>
<div class="section" id="auto-id-7">
<h2>実装してみる<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>実際に、簡単なアロケータを上の手法を使って Rust で実装してみる。まず、 <tt class="docutils literal">mmap</tt> のラップ API を用意しておく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal"> 10</span>
<span class="normal"> 11</span>
<span class="normal"> 12</span>
<span class="normal"> 13</span>
<span class="normal"> 14</span>
<span class="normal"> 15</span>
<span class="normal"> 16</span>
<span class="normal"> 17</span>
<span class="normal"> 18</span>
<span class="normal"> 19</span>
<span class="normal"> 20</span>
<span class="normal"> 21</span>
<span class="normal"> 22</span>
<span class="normal"> 23</span>
<span class="normal"> 24</span>
<span class="normal"> 25</span>
<span class="normal"> 26</span>
<span class="normal"> 27</span>
<span class="normal"> 28</span>
<span class="normal"> 29</span>
<span class="normal"> 30</span>
<span class="normal"> 31</span>
<span class="normal"> 32</span>
<span class="normal"> 33</span>
<span class="normal"> 34</span>
<span class="normal"> 35</span>
<span class="normal"> 36</span>
<span class="normal"> 37</span>
<span class="normal"> 38</span>
<span class="normal"> 39</span>
<span class="normal"> 40</span>
<span class="normal"> 41</span>
<span class="normal"> 42</span>
<span class="normal"> 43</span>
<span class="normal"> 44</span>
<span class="normal"> 45</span>
<span class="normal"> 46</span>
<span class="normal"> 47</span>
<span class="normal"> 48</span>
<span class="normal"> 49</span>
<span class="normal"> 50</span>
<span class="normal"> 51</span>
<span class="normal"> 52</span>
<span class="normal"> 53</span>
<span class="normal"> 54</span>
<span class="normal"> 55</span>
<span class="normal"> 56</span>
<span class="normal"> 57</span>
<span class="normal"> 58</span>
<span class="normal"> 59</span>
<span class="normal"> 60</span>
<span class="normal"> 61</span>
<span class="normal"> 62</span>
<span class="normal"> 63</span>
<span class="normal"> 64</span>
<span class="normal"> 65</span>
<span class="normal"> 66</span>
<span class="normal"> 67</span>
<span class="normal"> 68</span>
<span class="normal"> 69</span>
<span class="normal"> 70</span>
<span class="normal"> 71</span>
<span class="normal"> 72</span>
<span class="normal"> 73</span>
<span class="normal"> 74</span>
<span class="normal"> 75</span>
<span class="normal"> 76</span>
<span class="normal"> 77</span>
<span class="normal"> 78</span>
<span class="normal"> 79</span>
<span class="normal"> 80</span>
<span class="normal"> 81</span>
<span class="normal"> 82</span>
<span class="normal"> 83</span>
<span class="normal"> 84</span>
<span class="normal"> 85</span>
<span class="normal"> 86</span>
<span class="normal"> 87</span>
<span class="normal"> 88</span>
<span class="normal"> 89</span>
<span class="normal"> 90</span>
<span class="normal"> 91</span>
<span class="normal"> 92</span>
<span class="normal"> 93</span>
<span class="normal"> 94</span>
<span class="normal"> 95</span>
<span class="normal"> 96</span>
<span class="normal"> 97</span>
<span class="normal"> 98</span>
<span class="normal"> 99</span>
<span class="normal">100</span>
<span class="normal">101</span>
<span class="normal">102</span>
<span class="normal">103</span>
<span class="normal">104</span>
<span class="normal">105</span>
<span class="normal">106</span>
<span class="normal">107</span>
<span class="normal">108</span>
<span class="normal">109</span>
<span class="normal">110</span>
<span class="normal">111</span>
<span class="normal">112</span>
<span class="normal">113</span>
<span class="normal">114</span>
<span class="normal">115</span>
<span class="normal">116</span>
<span class="normal">117</span>
<span class="normal">118</span>
<span class="normal">119</span>
<span class="normal">120</span>
<span class="normal">121</span>
<span class="normal">122</span>
<span class="normal">123</span>
<span class="normal">124</span>
<span class="normal">125</span>
<span class="normal">126</span>
<span class="normal">127</span>
<span class="normal">128</span>
<span class="normal">129</span>
<span class="normal">130</span>
<span class="normal">131</span>
<span class="normal">132</span>
<span class="normal">133</span>
<span class="normal">134</span>
<span class="normal">135</span>
<span class="normal">136</span>
<span class="normal">137</span>
<span class="normal">138</span>
<span class="normal">139</span>
<span class="normal">140</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">mod</span> <span class="nn">sys</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">use</span><span class="w"> </span><span class="n">std</span>::<span class="p">{</span><span class="n">error</span>::<span class="n">Error</span><span class="p">,</span><span class="w"> </span><span class="n">ptr</span>::<span class="n">NonNull</span><span class="p">};</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">type</span> <span class="nc">AnyNonNull</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">NonNull</span><span class="o"><</span><span class="n">libc</span>::<span class="n">c_void</span><span class="o">></span><span class="p">;</span>
<span class="w"> </span><span class="sd">/// ページサイズを取得する。mmap で確保する領域はこのページサイズの倍数になってる必要がある。</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">get_pagesize</span><span class="p">()</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">pagesize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">libc</span>::<span class="n">sysconf</span><span class="p">(</span><span class="n">libc</span>::<span class="n">_SC_PAGE_SIZE</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">pagesize</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">std</span>::<span class="n">io</span>::<span class="n">Error</span>::<span class="n">last_os_error</span><span class="p">().</span><span class="n">into</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">pagesize</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sd">/// 仮想メモリ空間の一部を長さ分だけ予約する。</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">reserve</span><span class="p">(</span><span class="n">len</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">AnyNonNull</span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">libc</span>::<span class="n">mmap</span><span class="p">(</span>
<span class="w"> </span><span class="n">std</span>::<span class="n">ptr</span>::<span class="n">null_mut</span><span class="p">(),</span>
<span class="w"> </span><span class="n">len</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_NONE</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_ANONYMOUS</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_PRIVATE</span><span class="p">,</span>
<span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_FAILED</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">std</span>::<span class="n">io</span>::<span class="n">Error</span>::<span class="n">last_os_error</span><span class="p">().</span><span class="n">into</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">NonNull</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="n">ptr</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cp">#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">enum</span> <span class="nc">CommitStrategy</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Mprotect</span><span class="p">,</span>
<span class="w"> </span><span class="n">MmapFixed</span><span class="p">,</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sd">/// 予約された領域の一部を使用できるようにする。</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">commit</span><span class="p">(</span>
<span class="w"> </span><span class="n">addr</span>: <span class="nc">AnyNonNull</span><span class="p">,</span>
<span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">,</span>
<span class="w"> </span><span class="n">prefer_strategy</span>: <span class="nc">CommitStrategy</span><span class="p">,</span>
<span class="w"> </span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">CommitStrategy</span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">prefer_strategy</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">CommitStrategy</span>::<span class="n">Mprotect</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// mprotect は Linux 4.9 以上でないと使えない。</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">libc</span>::<span class="n">mprotect</span><span class="p">(</span>
<span class="w"> </span><span class="n">addr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
<span class="w"> </span><span class="n">len</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_READ</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_WRITE</span><span class="p">,</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">CommitStrategy</span>::<span class="n">Mprotect</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// MAP_FIXED での上書きマッピングは本来非推奨。</span>
<span class="w"> </span><span class="c1">// ただ、mprotect が使えない環境は存在するのでフォールバックしておく。</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">libc</span>::<span class="n">mmap</span><span class="p">(</span>
<span class="w"> </span><span class="n">addr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
<span class="w"> </span><span class="n">len</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_READ</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_WRITE</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_ANONYMOUS</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_PRIVATE</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_FIXED</span><span class="p">,</span>
<span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_FAILED</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">std</span>::<span class="n">io</span>::<span class="n">Error</span>::<span class="n">last_os_error</span><span class="p">().</span><span class="n">into</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">CommitStrategy</span>::<span class="n">MmapFixed</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="cp">#[allow(unused)]</span>
<span class="w"> </span><span class="cp">#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">enum</span> <span class="nc">DecommitStrategy</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Mprotect</span><span class="p">,</span>
<span class="w"> </span><span class="n">MmapFixed</span><span class="p">,</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sd">/// 予約された領域の一部の使用をやめる。予約されたままだが、物理メモリへのマッピングは解かれる。今回は使用しない。</span>
<span class="w"> </span><span class="cp">#[allow(unused)]</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">decommit</span><span class="p">(</span>
<span class="w"> </span><span class="n">addr</span>: <span class="nc">AnyNonNull</span><span class="p">,</span>
<span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">,</span>
<span class="w"> </span><span class="n">prefer_strategy</span>: <span class="nc">DecommitStrategy</span>
<span class="w"> </span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">DecommitStrategy</span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">prefer_strategy</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">DecommitStrategy</span>::<span class="n">Mprotect</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">libc</span>::<span class="n">mprotect</span><span class="p">(</span>
<span class="w"> </span><span class="n">addr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
<span class="w"> </span><span class="n">len</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_NONE</span><span class="p">,</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">DecommitStrategy</span>::<span class="n">Mprotect</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">libc</span>::<span class="n">mmap</span><span class="p">(</span>
<span class="w"> </span><span class="n">addr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span>
<span class="w"> </span><span class="n">len</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_NONE</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_ANONYMOUS</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_PRIVATE</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_FIXED</span><span class="p">,</span>
<span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_FAILED</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">std</span>::<span class="n">io</span>::<span class="n">Error</span>::<span class="n">last_os_error</span><span class="p">().</span><span class="n">into</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">DecommitStrategy</span>::<span class="n">MmapFixed</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sd">/// 仮想メモリ空間の一部を使用可能な状態で切り出す。</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">alloc</span><span class="p">(</span><span class="n">len</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">AnyNonNull</span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">libc</span>::<span class="n">mmap</span><span class="p">(</span>
<span class="w"> </span><span class="n">std</span>::<span class="n">ptr</span>::<span class="n">null_mut</span><span class="p">(),</span>
<span class="w"> </span><span class="n">len</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_READ</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">PROT_WRITE</span><span class="p">,</span>
<span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_ANONYMOUS</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_PRIVATE</span><span class="p">,</span>
<span class="w"> </span><span class="o">-</span><span class="mi">1</span><span class="p">,</span>
<span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">ptr</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">libc</span>::<span class="n">MAP_FAILED</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">std</span>::<span class="n">io</span>::<span class="n">Error</span>::<span class="n">last_os_error</span><span class="p">().</span><span class="n">into</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">NonNull</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="n">ptr</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sd">/// マッピング済みの領域のマッピングを解除する。新たに alloc / reserve で使用できるようになる。</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">release</span><span class="p">(</span><span class="n">addr</span>: <span class="nc">AnyNonNull</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="p">(),</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">libc</span>::<span class="n">munmap</span><span class="p">(</span><span class="n">addr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">(),</span><span class="w"> </span><span class="n">len</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">std</span>::<span class="n">io</span>::<span class="n">Error</span>::<span class="n">last_os_error</span><span class="p">().</span><span class="n">into</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(())</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><a class="reference external" href="https://docs.rs/crate/libc/latest">libc crate</a> を通してシステムコールを今回使う範囲で使いやすいように呼んでる。ま、それぞれの詳細はシステムコールのマニュアルを読んでもらうとして、基本的な用途は以下の感じ:</p>
<dl class="docutils">
<dt><tt class="docutils literal">get_pagesize</tt></dt>
<dd>ページサイズを取得する API。<tt class="docutils literal">reserve</tt> や <tt class="docutils literal">commit</tt>、 <tt class="docutils literal">alloc</tt> を呼ぶ際、指定する長さがページサイズでアラインされてる、つまりページサイズの倍数になっている必要があるため、その計算のために用意している。</dd>
<dt><tt class="docutils literal">reserve</tt></dt>
<dd>最初に glibc malloc のメモリ管理と独立した連続領域の予約を行うための API。アクセス権限はなく、物理メモリにもマッピングされないが指定した長さ分仮想メモリアドレスが予約された領域の先頭のポインタが返ってくる。</dd>
<dt><tt class="docutils literal">commit</tt></dt>
<dd>予約した領域を使う際に、物理メモリへのマッピングを行えるようにする API。 <tt class="docutils literal">MAP_PRIVATE</tt> での予約なので、遅延書き込み、つまり書き込みが起こるまで実際には独自の物理メモリへのマッピングは起きないが、気分的にはメモリ割り当てのような立ち位置。なお、通常は <tt class="docutils literal">mprotect</tt> を使うのだが、 <tt class="docutils literal">mprotect</tt> は Linux 4.9 で導入された割と新参のシステムコールなので広く使われてる言語では移植性などを考え <tt class="docutils literal">mmap</tt> の <tt class="docutils literal">MAP_FIXED</tt> モードへのフォールバックが用意されているか、Go ではそっちしか使ってないみたいな状況。今回は、 <tt class="docutils literal">mprotect</tt> が使えるならそっちを使う、使えないなら以降は <tt class="docutils literal">MAP_FIXED</tt> を使うという小細工を施せるようにしている。なお、厳密には <tt class="docutils literal">mprotect</tt> のエラーコードをちゃんとみて、対応してない場合のエラーコードのみフォールバックを発動させるのがお行儀が良い。</dd>
<dt><tt class="docutils literal">decommit</tt></dt>
<dd>今回は色々実装が面倒なので使用しないが、 <tt class="docutils literal">commit</tt> した領域の物理メモリへのマッピングを解除する、つまり使わなくなった領域をメモリに載せるのをやめる API。呼んで直後にマッピングが解除されるとは限らないが、少なくともページの追い出しで優先的に追い出されるようにはなる。 <tt class="docutils literal">commit</tt> と同じようなフォールバックを設けている。</dd>
<dt><tt class="docutils literal">alloc</tt></dt>
<dd>一旦予約するステップを踏まないで、直接メモリ領域を使用可能状態で確保する API。今回のアロケータ実装では、glibc malloc に少しならって、小さいブロックは連続領域に、ある程度大きいブロックはページサイズでアラインしてこの <tt class="docutils literal">alloc</tt> で直接確保するようにする。</dd>
<dt><tt class="docutils literal">release</tt></dt>
<dd><tt class="docutils literal">reserve</tt> や <tt class="docutils literal">alloc</tt> で確保した領域を解放し、その仮想メモリアドレスを再度利用できるようにする API。今回は <tt class="docutils literal">alloc</tt> で確保した領域のみに使用する。</dd>
</dl>
<p>これらの API を使って、簡単なシングルスレッドのみ対応のアロケータを作ってみる。今回実装するアロケータの概要は以下のようになる:</p>
<ul class="simple">
<li>1kB 以下のブロックは連続領域に確保しサイズのクラス毎にリストで管理、それ以外のブロックは <tt class="docutils literal">alloc</tt>、 <tt class="docutils literal">release</tt> で管理する。</li>
<li>ブロックにはヘッダを付け、連続領域に確保した場合はブロックサイズのクラス、それ以外の場合はブロックサイズを持っておく。</li>
</ul>
<p>まず幾つかパラメータを宣言しておく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">const</span><span class="w"> </span><span class="n">MAX_HEAP_SIZE</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="mi">40</span><span class="p">;</span>
<span class="k">const</span><span class="w"> </span><span class="n">SUBHEAP_COUNT</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="mi">7</span><span class="p">;</span>
<span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">block_size_of_subheap</span><span class="p">(</span><span class="n">class_of_subheap</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="kt">usize</span> <span class="p">{</span>
<span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o"><<</span><span class="w"> </span><span class="p">(</span><span class="n">class_of_subheap</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">const</span><span class="w"> </span><span class="n">MAX_BLOCK_SIZE</span>: <span class="kt">usize</span> <span class="o">=</span><span class="w"> </span><span class="n">block_size_of_subheap</span><span class="p">(</span><span class="n">SUBHEAP_COUNT</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="sd">/// * `alignment` - A power of 2.</span>
<span class="k">const</span><span class="w"> </span><span class="k">fn</span> <span class="nf">aligned_size</span><span class="p">(</span><span class="n">original</span>: <span class="kt">usize</span><span class="p">,</span><span class="w"> </span><span class="n">alignment</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="kt">usize</span> <span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">mask</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">alignment</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="n">original</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">original</span><span class="p">.</span><span class="n">reverse_bits</span><span class="p">()</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">mask</span><span class="p">)</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">MAX_HEAP_SIZE</tt> は今回はお遊びなので適当に大きな値を設定している。プロダクションに載せる際は、ちゃんと物理メモリの上限を取ってきてそこから数値を決めるのがいいんじゃないだろうか。 <tt class="docutils literal">SUBHEAP_COUNT</tt> はサイズのクラス分けの数を表している。流石に全てのサイズに対してフリーリストを作るのは色々無駄なので、通常サイズをクラス分けしてある程度無駄が生じるのを許容してフィットするクラスの最大サイズで領域確保が行われる。今回もそれに倣い、ブロックサイズ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span></span> に対して <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mrow><mo stretchy="false">(</mo><msub><mi>c</mi><mi>m</mi></msub><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></msup><mo><</mo><mi>m</mi><mo>≤</mo><msup><mn>2</mn><msub><mi>c</mi><mi>m</mi></msub></msup></mrow><annotation encoding="application/x-tex">2^{(c_m - 1)} < m \leq 2^{c_m}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9271em;vertical-align:-0.0391em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight">1</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span> を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>c</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">c_m</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span></span> のクラスと考え、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><msub><mi>c</mi><mi>m</mi></msub></msup></mrow><annotation encoding="application/x-tex">2^{c_m}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span> サイズのブロックとして確保する。ここら辺は、例えば Go だと 64 個ぐらいクラスがあり、クラス分けももう少し工夫してある。サイズからのクラスの特定に要する時間とよく使われるサイズ種別への対応のバランスを取るのが大事。 <tt class="docutils literal">block_size_of_subheap</tt> はクラスの最大ブロックサイズを返す。 <tt class="docutils literal">MAX_BLOCK_SIZE</tt> は連続領域に確保されるブロックの最大サイズとなる。 <tt class="docutils literal">aligned_size</tt> はユーティリティで、 <tt class="docutils literal">original <= x * alignment</tt> となる最小の <tt class="docutils literal">x</tt> を計算する。主にページサイズの倍数となるようサイズ調節するのに使用する。</p>
<p>次にアロケータ用のデータ構造を定義する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">Allocator</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// immutable</span>
<span class="w"> </span><span class="n">pagesize</span>: <span class="kt">usize</span><span class="p">,</span>
<span class="w"> </span><span class="n">heap_end</span>: <span class="nc">sys</span>::<span class="n">AnyNonNull</span><span class="p">,</span>
<span class="w"> </span><span class="c1">// mutable</span>
<span class="w"> </span><span class="n">free_lists</span>: <span class="p">[</span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">FreeHeader</span><span class="p">;</span><span class="w"> </span><span class="n">SUBHEAP_COUNT</span><span class="p">],</span>
<span class="w"> </span><span class="n">active_heap_end</span>: <span class="nc">sys</span>::<span class="n">AnyNonNull</span><span class="p">,</span>
<span class="w"> </span><span class="n">commited_heap_end</span>: <span class="nc">sys</span>::<span class="n">AnyNonNull</span><span class="p">,</span>
<span class="w"> </span><span class="n">prefer_commit_strategy</span>: <span class="nc">sys</span>::<span class="n">CommitStrategy</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">struct</span> <span class="nc">Header</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">size_or_class_of_subheap</span>: <span class="kt">usize</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">struct</span> <span class="nc">FreeHeader</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="cp">#[allow(unused)]</span>
<span class="w"> </span><span class="n">header</span>: <span class="nc">Header</span><span class="p">,</span>
<span class="w"> </span><span class="n">next</span>: <span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">FreeHeader</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">impl</span><span class="w"> </span><span class="n">Allocator</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">init</span><span class="p">()</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="bp">Self</span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">pagesize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sys</span>::<span class="n">get_pagesize</span><span class="p">()</span><span class="o">?</span><span class="p">;</span>
<span class="w"> </span><span class="fm">assert!</span><span class="p">(</span><span class="n">MAX_HEAP_SIZE</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="n">pagesize</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">heap_begin</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sys</span>::<span class="n">reserve</span><span class="p">(</span><span class="n">MAX_HEAP_SIZE</span><span class="p">)</span><span class="o">?</span><span class="p">;</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">heap_end</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">NonNull</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="n">heap_begin</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">add</span><span class="p">(</span><span class="n">MAX_HEAP_SIZE</span><span class="p">));</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">free_lists</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="n">std</span>::<span class="n">ptr</span>::<span class="n">null_mut</span><span class="p">();</span><span class="w"> </span><span class="n">SUBHEAP_COUNT</span><span class="p">];</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="bp">Self</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">pagesize</span><span class="p">,</span>
<span class="w"> </span><span class="n">heap_end</span><span class="p">,</span>
<span class="w"> </span><span class="n">free_lists</span><span class="p">,</span>
<span class="w"> </span><span class="n">active_heap_end</span>: <span class="nc">heap_begin</span><span class="p">,</span>
<span class="w"> </span><span class="n">commited_heap_end</span>: <span class="nc">heap_begin</span><span class="p">,</span>
<span class="w"> </span><span class="n">prefer_commit_strategy</span>: <span class="nc">sys</span>::<span class="n">CommitStrategy</span>::<span class="n">Mprotect</span><span class="p">,</span>
<span class="w"> </span><span class="p">})</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">..</span><span class="p">.</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>アロケータは主に、フリーブロックのリストと、連続領域の使用済み地点を持つ。</p>
<p><tt class="docutils literal">free_lists</tt> がフリーブロックのリストで、 <tt class="docutils literal">free</tt> されたブロックはここに追加され、次回の <tt class="docutils literal">alloc</tt> で再利用される。リストは、生ポインタ使った単方向リストで実装している。この辺は、Rust 標準アロケータに頼らないで、かつメモリレイアウトを簡潔にするため。</p>
<p><tt class="docutils literal">active_heap_end</tt> は現在使用している領域の最後を表す。この地点からなら新たにブロック用に切り出しが可能。ただ、 <tt class="docutils literal">active_heap_end</tt> はページサイズでアラインされてるとは限らないので、実際に <tt class="docutils literal">commit</tt> でアクセス権限をつけてる領域とはズレてる可能性がある。 <tt class="docutils literal">commit</tt> が完了してる地点を表すのが <tt class="docutils literal">commit_heap_end</tt>。ブロック用に切り出す領域がまだコミット済みじゃない領域まで必要とする場合は、まずその領域分ページサイズアラインされた領域を <tt class="docutils literal">commit</tt> し、その後使用する分だけ切り出すことになる。</p>
<p>アロケータ初期化の時点では、まず連続領域用の仮想メモリアドレスの予約が走り、空のフリーリストと空の連続領域からスタートとなる。その後の割り当て <tt class="docutils literal">alloc</tt> と解放 <tt class="docutils literal">free</tt> の実装は以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">impl</span><span class="w"> </span><span class="n">Allocator</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">alloc</span><span class="o"><</span><span class="n">T</span>: <span class="nb">Sized</span><span class="o">></span><span class="p">(</span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">NonNull</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">alloc_by_size</span><span class="p">(</span><span class="n">size_of</span>::<span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">alloc_by_size</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">(</span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">NonNull</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">MAX_BLOCK_SIZE</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">class_of_subheap</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="n">SUBHEAP_COUNT</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">len</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">block_size_of_subheap</span><span class="p">(</span><span class="n">class_of_subheap</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">alloc_on_subheap</span><span class="p">(</span><span class="n">class_of_subheap</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">alloc_on_subheap</span><span class="p">(</span><span class="n">SUBHEAP_COUNT</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">alloc_on_external</span><span class="p">(</span><span class="n">len</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">free</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">(</span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">ptr</span>: <span class="nc">NonNull</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="p">(),</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">allocated_ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">ptr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">libc</span>::<span class="n">c_void</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="n">offset</span><span class="p">(</span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="n">size_of</span>::<span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="p">()</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">isize</span><span class="p">));</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">allocated_ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">NonNull</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="n">allocated_ptr</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">Header</span><span class="p">);</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">size_or_class_of_subheap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">allocated_ptr</span><span class="p">.</span><span class="n">as_ref</span><span class="p">().</span><span class="n">size_or_class_of_subheap</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">size_or_class_of_subheap</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">MAX_BLOCK_SIZE</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">class_of_subheap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">size_or_class_of_subheap</span><span class="p">;</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">free_on_subheap</span><span class="p">(</span><span class="n">allocated_ptr</span><span class="p">,</span><span class="w"> </span><span class="n">class_of_subheap</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">size_or_class_of_subheap</span><span class="p">;</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">free_on_external</span><span class="p">(</span><span class="n">allocated_ptr</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>基本的にどちらもブロックサイズが連続領域のブロックの最大サイズ以下かで分岐し、それぞれの処理を行う。連続領域以外での処理の方が簡単なので、まずそっちを見ておく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">impl</span><span class="w"> </span><span class="n">Allocator</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="o">..</span><span class="p">.</span>
<span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">alloc_on_external</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">(</span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">len</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">NonNull</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">allocated_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">aligned_size</span><span class="p">(</span><span class="n">len</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">size_of</span>::<span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="p">(),</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">pagesize</span><span class="p">);</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">allocated_ptr</span>: <span class="nc">NonNull</span><span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sys</span>::<span class="n">alloc</span><span class="p">(</span><span class="n">allocated_size</span><span class="p">)</span><span class="o">?</span><span class="p">.</span><span class="n">cast</span><span class="p">();</span>
<span class="w"> </span><span class="o">*</span><span class="n">allocated_ptr</span><span class="p">.</span><span class="n">as_mut</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Header</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">size_or_class_of_subheap</span>: <span class="nc">allocated_size</span><span class="p">,</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">allocated_ptr</span><span class="p">.</span><span class="n">cast</span><span class="p">())</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">free_on_external</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">addr</span>: <span class="nc">NonNull</span><span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="p">,</span><span class="w"> </span><span class="n">size</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="p">(),</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">sys</span>::<span class="n">release</span><span class="p">(</span><span class="n">addr</span><span class="p">.</span><span class="n">cast</span><span class="p">(),</span><span class="w"> </span><span class="n">size</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">..</span><span class="p">.</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>ヘッダつけてページアラインしたサイズの領域を <tt class="docutils literal"><span class="pre">sys::alloc</span></tt> で確保して返し、ヘッダからサイズ特定して <tt class="docutils literal"><span class="pre">sys::release</span></tt> で解放してるだけ。ま、こっちはいいだろう。連続領域での確保の方は以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">impl</span><span class="w"> </span><span class="n">Allocator</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="o">..</span><span class="p">.</span>
<span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">alloc_on_subheap</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">(</span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">class_of_subheap</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">NonNull</span><span class="o"><</span><span class="n">T</span><span class="o">></span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">NonNull</span>::<span class="n">new</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">free_lists</span><span class="p">[</span><span class="n">class_of_subheap</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nb">None</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">allocated_ptr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">extend_active_heap_end</span><span class="p">(</span><span class="n">class_of_subheap</span><span class="p">)</span><span class="o">?</span><span class="p">;</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">allocated_ptr</span>: <span class="nc">NonNull</span><span class="o"><</span><span class="n">libc</span>::<span class="n">c_void</span><span class="o">></span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">allocated_ptr</span><span class="p">.</span><span class="n">cast</span><span class="p">();</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">NonNull</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="n">allocated_ptr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">add</span><span class="p">(</span><span class="n">size_of</span>::<span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="p">())</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">T</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">free_ptr</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">free_lists</span><span class="p">[</span><span class="n">class_of_subheap</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">free_ptr</span><span class="p">.</span><span class="n">as_ref</span><span class="p">().</span><span class="n">next</span><span class="p">;</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">used_ptr</span>: <span class="nc">NonNull</span><span class="o"><</span><span class="n">libc</span>::<span class="n">c_void</span><span class="o">></span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">free_ptr</span><span class="p">.</span><span class="n">cast</span><span class="p">();</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">NonNull</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="n">used_ptr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">add</span><span class="p">(</span><span class="n">size_of</span>::<span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="p">())</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="o">*</span><span class="k">mut</span><span class="w"> </span><span class="n">T</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">free_on_subheap</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">addr</span>: <span class="nc">NonNull</span><span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="p">,</span><span class="w"> </span><span class="n">class_of_subheap</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="p">(),</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">addr</span>: <span class="nc">NonNull</span><span class="o"><</span><span class="n">FreeHeader</span><span class="o">></span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">addr</span><span class="p">.</span><span class="n">cast</span><span class="p">();</span>
<span class="w"> </span><span class="n">addr</span><span class="p">.</span><span class="n">as_mut</span><span class="p">().</span><span class="n">next</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">free_lists</span><span class="p">[</span><span class="n">class_of_subheap</span><span class="p">];</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">free_lists</span><span class="p">[</span><span class="n">class_of_subheap</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">addr</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">();</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(())</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">..</span><span class="p">.</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>こっちは、クラスのフリーリストに再利用可能なブロックがあればそれを使い、なければ使用可能領域を必要なだけ広げて切り出すのが割り当てになり、フリーリストに単に繋げるのが開放になる。更新処理でのロックなどは取ってないので、シングルスレッド専用。マルチスレッド対応する際は、排他処理以外にも色々考えるべきことがあるので、今回は考えないことにしておく。最後に使用可能領域の拡張は、以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">impl</span><span class="w"> </span><span class="n">Allocator</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="o">..</span><span class="p">.</span>
<span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">extend_active_heap_end</span><span class="p">(</span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">class_of_subheap</span>: <span class="kt">usize</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">Result</span><span class="o"><</span><span class="n">NonNull</span><span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="p">,</span><span class="w"> </span><span class="nb">Box</span><span class="o"><</span><span class="k">dyn</span><span class="w"> </span><span class="n">Error</span><span class="o">>></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">allocated_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">size_of</span>::<span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">block_size_of_subheap</span><span class="p">(</span><span class="n">class_of_subheap</span><span class="p">);</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">new_active_heap_end</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">NonNull</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">active_heap_end</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">add</span><span class="p">(</span><span class="n">allocated_size</span><span class="p">));</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">heap_end</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">new_active_heap_end</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="fm">format!</span><span class="p">(</span><span class="s">"Failed to extend heap size."</span><span class="p">).</span><span class="n">into</span><span class="p">());</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">commited_heap_end</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="n">new_active_heap_end</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">committed_size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">aligned_size</span><span class="p">(</span>
<span class="w"> </span><span class="n">new_active_heap_end</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">offset_from</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">active_heap_end</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">())</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="kt">usize</span><span class="p">,</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">pagesize</span><span class="p">,</span>
<span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">prefer_commit_strategy</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sys</span>::<span class="n">commit</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">commited_heap_end</span><span class="p">,</span><span class="w"> </span><span class="n">committed_size</span><span class="p">,</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">prefer_commit_strategy</span><span class="p">)</span><span class="o">?</span><span class="p">;</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">commited_heap_end</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">NonNull</span>::<span class="n">new_unchecked</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">commited_heap_end</span><span class="p">.</span><span class="n">as_ptr</span><span class="p">().</span><span class="n">add</span><span class="p">(</span><span class="n">committed_size</span><span class="p">));</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">allocated_ptr</span>: <span class="nc">NonNull</span><span class="o"><</span><span class="n">Header</span><span class="o">></span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">active_heap_end</span><span class="p">.</span><span class="n">cast</span><span class="p">();</span>
<span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">active_heap_end</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">new_active_heap_end</span><span class="p">;</span>
<span class="w"> </span><span class="o">*</span><span class="n">allocated_ptr</span><span class="p">.</span><span class="n">as_mut</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Header</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">size_or_class_of_subheap</span>: <span class="nc">class_of_subheap</span><span class="p">,</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">allocated_ptr</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>まずヘッダ付きの領域サイズを計算し、コミット済みの領域が足りなければまず追加のコミットを行う。その後、使用可能領域を広げその領域をブロック用の領域として返す。こんな感じで glibc malloc と併用可能な自前アロケータを実装できる。全体のコードは、<a class="reference external" href="https://github.com/mizunashi-mana/sample-alloc-by-freelist">https://github.com/mizunashi-mana/sample-alloc-by-freelist</a> においておいた。今回の例だとそもそも連続領域は実は必要ないので、あくまで参考用という感じではある。</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、 <tt class="docutils literal">mmap</tt> の <tt class="docutils literal">MAP_PRIVATE|MAP_ANONYMOUS</tt> モードを利用した glibc malloc と併用可能な動的メモリ管理の実装方法について紹介した。仮想メモリ空間が少し小さい 32bit 環境では別の方法を考えた方がいいだろうが、x86 64、ARM64 環境の Linux であればこの方法で問題は起きないだろう。もちろん、連続空間がそもそも必要ないアロケーションアルゴリズムも世の中には色々あるので、その際はアドレスの予約までしないで <tt class="docutils literal">mmap</tt> で適宜領域を広げていっても良い。言語のランタイムを独自で作る場合はメモリ配置を工夫するだけでパフォーマンスが強く改善する場合もあるし、glibc malloc はメトリクスが少ないので独自にメトリクスを仕込みたい場合もある。そういった場合にアロケータを自作することは、よくあるだろう。その際にこの手法が役に立てば幸いだ。</p>
<p>これまであまり malloc の裏側がどうなってるのかなどあまり気にしたことなかったし、OS が頑張ってどうにかしてくれてるだろうぐらいに考えていたので、結構中身がデータ構造による工夫でどうにかなっていることが知れてよかった。おかげで動的メモリ管理については結構解像度上がった感がある。この辺は普段のプログラミングとか GC 作りとかにも応用していきたいなという感じ。ま、この辺最大限頑張ろうと思うとアーキテクチャ毎に工夫が必要になり、結構泥臭い部分も多いが。では、今回はこれで。</p>
<table class="docutils footnote" frame="void" id="virtual-memory-max-address" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td>正確には 16EB まで仮想メモリアドレスとして使える 64bit アーキテクチャは稀で、大体は 48bit、つまり 256TB ぐらいまでが限界になる。これは 64bit フルサポートは実益がないのに対して、アドレス変換テーブルの保存が大変だから。まあ、ただ 256TB までのサポートだと最近微妙になってきつつあったので、57bit、128PB サポートのものも出てきつつあるようだ。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="virtual-memory-introduction-by-konsulko" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td><a class="reference external" href="https://elinux.org/images/b/b0/Introduction_to_Memory_Management_in_Linux.pdf">https://elinux.org/images/b/b0/Introduction_to_Memory_Management_in_Linux.pdf</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="virtual-memory-layout-of-x86-64" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[3]</a></td><td><a class="reference external" href="https://www.kernel.org/doc/html/v5.8/x86/x86_64/mm.html">https://www.kernel.org/doc/html/v5.8/x86/x86_64/mm.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="man-of-mmap" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[4]</a></td><td><a class="reference external" href="https://www.man7.org/linux/man-pages/man2/mmap.2.html">https://www.man7.org/linux/man-pages/man2/mmap.2.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="glibc-sysmalloc-mmap-impl" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[5]</a></td><td><a class="reference external" href="https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=d0bbbf371048ee8aa8a30c03b189cb268b8ad9e4;hb=HEAD#l2420">https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=d0bbbf371048ee8aa8a30c03b189cb268b8ad9e4;hb=HEAD#l2420</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/09/impl-custom-alloc-integrated-with-malloc.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/09/impl-custom-alloc-integrated-with-malloc.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Systemd ユニットのセキュリティスコアを改善する2023-08-06T05:25:05+09:002023-08-06T05:25:05+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-08-06:/blog/posts/2023/08/systemd-analyze-security/<p>systemd は Linux の標準的なシステム・サービスマネージャで、sysvinit の代替の init プロセスとなることを目指して開発されたソフ …</p><p>systemd は Linux の標準的なシステム・サービスマネージャで、sysvinit の代替の init プロセスとなることを目指して開発されたソフトウェアである。長らく色々論争が行われ、紆余曲折はあったものの、現在ではほとんどの Linux ディストリビューションが標準的に init として採用している。SysV のサービスが秘伝の起動スクリプトにより管理されてきたのに対して、systemd ではサービスを記述するユニットファイルによりサービスを管理する。黎明期は systemd の方は様子見で、SysV 用の起動スクリプトだけを提供するプロジェクトも多かったが、現在は systemd ユニットを標準的に提供するプロジェクトも増えている。</p>
<p>さて、サービスを管理する上で重要なことの一つがセキュリティだ。サービスは基本的に長期間動くプロセスで、権限も大きく、他のサービスとの連携も行われる。そのため、外部からの攻撃にも晒されやすく、セキュリティホールにもなりやすい。もちろん、サービスコードそのものが万全なセキュリティを搭載しているのも重要だが、万全のセキュリティというものは存在しないため、サービスマネージャにおいてもあるサービスへの攻撃の防御と影響範囲の最小化を事前に行っておくのが良い。systemd はそのための機能をいくつか提供している。今回は、その機能を使用したユニットのセキュリティ改善方法を紹介する。</p>
<div class="section" id="auto-id-1">
<h2>systemd によるセキュリティスコア<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>systemd にはセキュリティ機能の解析と、スコア評価を行う機能が提供されている:</p>
<pre class="literal-block">
$ systemd-analyze security systemd-resolved
NAME DESCRIPTION EXPOSURE
✓ SystemCallFilter=~@swap System call allow list defined for service, and @swap is not included
✗ SystemCallFilter=~@resources System call allow list defined for service, and @resources is included (e.g. ioprio_set is allowed) 0.2
✓ SystemCallFilter=~@reboot System call allow list defined for service, and @reboot is not included
✓ SystemCallFilter=~@raw-io System call allow list defined for service, and @raw-io is not included
✗ SystemCallFilter=~@privileged System call allow list defined for service, and @privileged is included (e.g. chown is allowed) 0.2
...
✗ UMask= Files created by service are world-readable by default 0.1
→ Overall exposure level for systemd-resolved.service: 2.1 OK 🙂
</pre>
<p>ロード済みのユニットに対して、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> security <ユニット名></tt> の形で実行すると、セキュリティ設定の有効可否と設定レベルを出してくれる。レベルは 0 - 10 の間でつけられ、レベルが小さいほどセキュリティ機能の有効度が高く、レベルが大きいほど改善の余地があるということになる。</p>
<p>基本的にはこれを見ながら、バツマークがついてるところの中でスコアが高いものから対応していくのが良い。もちろん、何も考えずに設定を入れてもだめで、サービスコードとの兼ね合いを見ながら必要だと思われる設定だけをつけていけば良い。では、具体的にそれぞれ指摘される設定をそれぞれ見ていこう。</p>
</div>
<div class="section" id="auto-id-2">
<h2>systemd のセキュリティ機能<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>systemd のセキュリティ機能は、概ね3種類ある:</p>
<dl class="docutils">
<dt>サンドボックス化</dt>
<dd>サービスのプロセス専用の隔離リソースを作り、影響が他のサービスや関係ないリソースに及ばないようにする機能。</dd>
<dt>制限</dt>
<dd>サービスに不要なリソースへのアクセスを制限することで、影響を最低限に抑える機能。</dd>
<dt>デフォルト挙動改善</dt>
<dd>影響が大きい機能のデフォルトの挙動を、セキュリティ的に望ましい方向に改善する機能。</dd>
</dl>
<p>基本的に外部からの攻撃というものは、典型的なパターンがある:</p>
<ol class="arabic simple">
<li>意図しないコード実行やリソース作成を行う</li>
<li>情報を集め、攻撃者に送信し、さらに意図しないコード実行やリソース作成を行う</li>
<li>マルウェアやランサムウェアを埋め込み、外部へのさらなる攻撃への中継点にしたり、アクセスできるリソースの改変を行い不正な取引の材料にしたりする</li>
</ol>
<p>逆に言えば、意図しないコード実行やリソース作成をしても情報を集められない、攻撃者に情報を送れないといった状況を作ったり、アクセスできるリソースを制限することで攻撃の影響範囲はかなり抑えられるということだ。つまり、サンドボックス化により他のリソースから隔離し、さらにできることを必要な範囲だけに制限することにより、典型的な攻撃は防御できる。もちろん、サービス自体やそこからアクセスが必要なリソースに脆弱性がありそれにより十分広い影響が出ることはあるため、サービスマネージャのセキュリティ機能だけに頼るのは問題だが、サービスのセキュリティに関して強力な補佐とはなるだろう。</p>
<p>では、それぞれ詳細を見ていく。まず、サンドボックス機能のスコアが高いものから:</p>
<dl class="docutils">
<dt><tt class="docutils literal">PrivateNetwork</tt></dt>
<dd><p class="first">専用のネットワーク名前空間を作り、それを使う。このオプションを有効にすると、ネットワークアクセスが内外問わず完全に遮断される。外部ネットワークへのアクセスなどを特にしないサービスでは、有効にしとくと良いだろう。これを有効化しておけば、ほとんどの攻撃から防御できるだろう。ただ、ネットワークアクセス自体は必要なサービスも多いことから、このオプションを有効にできるサービスはかなり限られるだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateNetwork=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateNetwork=</a></p>
</dd>
<dt><tt class="docutils literal">PrivateDevices</tt></dt>
<dd><p class="first">専用の <tt class="docutils literal">/dev</tt> マウンティングを行い、基本的な擬似デバイスだけを見えるようにする。これにより、物理デバイスやシステムデバイスなどは見えなくなり、攻撃を受けても取得できる情報が限定される。物理デバイスやシステムデバイスにアクセスするようなサービスは限られる為、基本的には有効にしておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateDevices=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateDevices=</a></p>
</dd>
<dt><tt class="docutils literal">PrivateMounts</tt></dt>
<dd><p class="first">マウント名前空間が専用に作成され、サービスが作成したマウントポイントがホストからは見えなくなる。これによりサービスが攻撃を受けて不正なマウントポイントを作成してしまったとしても、他のサービスには全く影響が出なくなるし、逆に他のサービスからサービスのマウントポイントが攻撃されることもなくなる。基本的に、そもそもマウントポイントを作成されるサービスは限られるため、マウント権限自体を無効化しとくのがいいだろうが、その上でだったり、他のサービスとマウントポイントを共有することがない場合は、このオプションを有効化しておくのがいいだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateMounts=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateMounts=</a></p>
</dd>
<dt><tt class="docutils literal">PrivateTmp</tt></dt>
<dd><p class="first">専用の一時ディレクトリ用ファイル名前空間を作り、それを使う。これにより、他のプロセスの一時ファイルを一時ディレクトリ経由で弄ることができなくなる。一時ディレクトリを利用したサービスロジックは、TOCTOU に関する問題を利用したセキュリティホールを持ちやすい為、攻撃対象になりやすい。また、他プロセスと一時ディレクトリを共有する必要は通常ないため、基本的には有効化しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=</a></p>
</dd>
<dt><tt class="docutils literal">PrivateUsers</tt></dt>
<dd><p class="first">サービス専用のユーザ名前空間を作り、root ユーザと実行ユーザだけがそのままマッピングし、他のユーザは nobody ユーザとしてマッピングした上で使う。これにより、リソースに対して紐づくユーザ情報が取得できないようになる。他ユーザと連携することがなければ、基本的に有効化しておくのがいいだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateUsers=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateUsers=</a></p>
</dd>
<dt><tt class="docutils literal">KeyringMode</tt></dt>
<dd><p class="first">セッションキーリングの設定制御を行う。 <tt class="docutils literal">KeyringMode=inherit</tt> を指定する場合は、特別なキーリング設定は行わず、カーネルのデフォルト動作が適用される。 <tt class="docutils literal">KeyringMode=private</tt> を指定する場合は、専用のセッションキーリングが作成され、どのユーザキーリングにもリンクされない。 <tt class="docutils literal">KeyringMode=shared</tt> を指定する場合は、 <tt class="docutils literal">private</tt> と同様専用のセッションキーリングが発行されるが、実行ユーザのキーリングにはリンクされる。デフォルトでは、 <tt class="docutils literal">private</tt> が指定されており、基本的にはここから変更する必要はないだろう。キーリングで管理される認証情報を他のサービスと共有することは、他のサービスが攻撃を受けた時重大な被害が及びかねない。基本的には他のサービスと切り離しておくべきだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#KeyringMode=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#KeyringMode=</a></p>
</dd>
<dt><tt class="docutils literal">RootDirectory</tt> / <tt class="docutils literal">RootImage</tt></dt>
<dd><p class="first">RootDirectory は chroot を使ってサービスのルートディレクトリを指定したディレクトリに変えることで、そのディレクトリより上位のディレクトリへのアクセスをファイルシステム上できなくする。RootImage はさらに、ディレクトリの代わりにデバイスノードを指定することでそのデバイスノードの隔離されたファイルシステムを使うようにする。</p>
<p>ファイルは重要なリソースで、それ故に攻撃対象になりやすい。ディレクトリトラバーサルなどの脆弱性をサービスコードが持っていると、他サービスやシステムリソースなどへのアクセスもできてしまい、それにより重大な結果をもたらす恐れもある。これを避ける根本的な手段は、そもそも他サービスやシステムリソースにファイルシステム上辿り着けないようにするのが一番良い。その時に出番となるオプション。ただ、流石にルートディレクトリを変えてしまうと、動的ライブラリの解決なども出来なくなるので、セキュリティ的に強力な反面運用は難しい。まあ、可能なら設定しておくぐらいでいいだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RootDirectory=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RootDirectory=</a></li>
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RootImage=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RootImage=</a></li>
</ul>
</dd>
</dl>
<p>次に制限のための機能を見ていく:</p>
<dl class="docutils">
<dt><tt class="docutils literal">User</tt> / <tt class="docutils literal">DynamicUser</tt></dt>
<dd><p class="first">このオプションは使ってる人も多いだろう。User オプションはサービスの実行ユーザを指定するオプション。DynamicUser も実行ユーザをルートユーザと異なるユーザにできるオプションで、こちらは有効にすると実行のたびに専用のユーザとグループを動的に作成して割り当ててくれる。</p>
<p>さて、systemd のサービスはデフォルトではルートユーザで動く。ルートユーザは様々な特権的権限を持っており、全てのディレクトリへアクセスできるし改変もできる。権限を他のユーザに付与したりすることも可能だ。逆に言えばこのユーザが乗っ取られると大変なことになる。またルートユーザの証跡は追いにくく、いつ何をそのサービスがしたのかも分からなくなりがちだ。そこで、サービスの実行専用ユーザを作成し、実行に必要な最小限の権限だけを与えて実行ユーザとすることで、そのサービスが攻撃者に乗っ取られても影響範囲を抑えることができ、また何をされたかの証跡が追いやすくなる。基本的にどちらかのオプションを使うことで、ルートユーザでのサービス実行は避けるのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#User=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#User=</a></li>
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DynamicUser=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DynamicUser=</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">RestrictNamespaces</tt></dt>
<dd><p class="first">アクセス可能な名前空間機能の種類を指定する。せっかくサンドボックス機能で名前空間を分離しても、他の名前空間が触れては意味がない。そこでこのオプションを併用することで、隔離をより強固にできる。名前空間管理機能に触るサービスは限られるだろうから、基本的には <tt class="docutils literal">RestrictNamespaces=true</tt> で全ての種類について有効化しておくのが良いだろう。もし、名前空間管理機能にアクセスする場合も、必要な種類のみホワイトリスト形式で除外しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man7/namespaces.7.html">https://man7.org/linux/man-pages/man7/namespaces.7.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">RestrictAddressFamilies=~AF_(INET|INET6)</span></tt></dt>
<dd><p class="first">IPv4 / IPv6 ソケットの作成を制限する。基本的に攻撃に持続性を持たせるには、リモートアクセスが必須となる。そうなると、攻撃元でリモートアクセス用のエンドポイントを作るか、攻撃先にリモートアクセス用のエンドポイントを作るかしかない。その一方が封じられることは、セキュリティの向上につながるだろう。もしサービスが IP ソケット作成を必要としないなら、指定しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/socket.2.html">https://man7.org/linux/man-pages/man2/socket.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">ProtectControlGroups</tt></dt>
<dd><p class="first">cgroup を読み込み専用にし、書き込みを無効化する。cgroup を変更できると、他サービスからリソースを奪ったり、保護機能を無効化したりできる。基本的なコンテナ管理サービス以外で cgroup の書き込み権限は必要ないだろうから、指定しておくのがいいだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectControlGroups=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectControlGroups=</a></p>
</dd>
<dt><tt class="docutils literal">ProtectKernelModules</tt></dt>
<dd><p class="first">カーネルモジュールの読み込みを無効化する。カーネルモジュールによるカーネル機能の拡張は、サービス提供者だけでなく、攻撃者にとっても強力な助っ人となり得る。カーネルモジュールの読み込みが必要なサービスは限られるだろうから、基本的には有効化しておくのがいいだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelModules=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelModules=</a></p>
</dd>
<dt><tt class="docutils literal">ProtectKernelTunables</tt></dt>
<dd><p class="first">カーネル変数を読み込み専用にし、書き込みを無効化する。カーネル変数の変更は、カーネルの重要な保護機能を無効化したり、攻撃に利用できるような機能の有効化に繋げられかねない。また、基本的に実行時に変更を必要とすることはないため、有効化しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelTunables=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelTunables=</a></p>
</dd>
<dt><tt class="docutils literal">ProtectKernelLogs</tt></dt>
<dd><p class="first">カーネルログのリングバッファを読み書きする権限を無効化する。カーネルログを取得すると、ホストの情報を取得し、さらなる攻撃に繋げられかねない。基本的にカーネルログを読み書きするサービスは限られるだろうから、有効化しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelLogs=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelLogs=</a></p>
</dd>
<dt><tt class="docutils literal">ProtectClock</tt></dt>
<dd><p class="first">サービスが、ハードウェアクロック、システムクロックの変更をできなくするオプション。時間に関する判定をバグらせるとセキュリティホールにつながることも多い。特にタイムスタンプを任意に固定できれば、攻撃の幅が広がることもある。まあ基本的にクロックを変更するサービスはあまりないと思うし、攻撃手段として利用できなくしておくのに越したことはないだろうから、基本的には有効にしておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectClock=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectClock=</a></p>
</dd>
<dt><tt class="docutils literal">ProtectHome</tt></dt>
<dd><p class="first">サービスから、 <tt class="docutils literal">/home</tt>、 <tt class="docutils literal">/root</tt>、 <tt class="docutils literal">/run/user</tt> を見えなくする、または読み込み専用にするオプション。 <tt class="docutils literal">ProtectHome=true</tt> と指定した場合、これらのディレクトリをサービス用の名前空間から隔離し、サービスから見えないようにする。 <tt class="docutils literal"><span class="pre">ProtectHome=read-only</span></tt> と指定した場合、これらのディレクトリを読み込み専用でマウントする。 <tt class="docutils literal">ProtectHome=tmpfs</tt> と指定した場合、一時ディレクトリとしてこれらのディレクトリを読み込み専用で作り、サービスからは実際のディレクトリではなく一時ディレクトリの方を参照するようにする。基本的にはサービスが実行時に書き込みを行うのは、実行時ディレクトリ、状態ディレクトリ、またはキャッシュディレクトリであるべきであり、ホームディレクトリを参照するべきではない。基本的に多くのサービスは、実行時のデータディレクトリを指定できる場合が多い。それらの機能を通してホームディレクトリ以外を実行時ディレクトリとして選べるなら、書き込み可能な範囲を押さえ、他のユーザへの影響をなくすためにも有効化しておくのが良いだろう。なお、たまにホームディレクトリが全く存在しないと立ち上がらないサービスもあるため、その場合は一時ディレクトリによるマウントを指定しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=</a></p>
</dd>
<dt><tt class="docutils literal">ProtectSystem</tt></dt>
<dd><p class="first">システムディレクトリを読み込み専用でマウントし、書き込みを禁止するオプション。 <tt class="docutils literal">ProtectSystem=true</tt> の場合 <tt class="docutils literal">/usr</tt> とブートローダのディレクトリが、 <tt class="docutils literal">ProtectSystem=full</tt> の場合さらに <tt class="docutils literal">/etc</tt> ディレクトリが読み込み専用でマウントされる。 <tt class="docutils literal">ProtectSystem=strict</tt> の場合は、API 用の <tt class="docutils literal">/dev</tt>、 <tt class="docutils literal">/proc</tt>、 <tt class="docutils literal">/sys</tt> 以外のディレクトリが全て読み込み専用でマウントされる。これは後述する <tt class="docutils literal">ReadWritePaths</tt> で例外を設定できる。また、読み込み専用でマウントされる対象はあくまでホストのディレクトリであり、 <tt class="docutils literal">PrivateTmp</tt> などのサンドボックス機能で生成されるサービス専用のマウントポイントは書き込み可能のまま維持される。ウイルスをインストールするにしろ、他のサービスを攻撃するにしろ、システムディレクトリに書き込みを行うことは攻撃の基本的な手段だ。よって、書き込み可能なディレクトリを少なくしておくことは、重要なセキュリティ施策になる。また、書き込みが起こるディレクトリを把握しておくことは、各サービスが攻撃を受けた時の影響範囲を把握する上で重要だ。基本的には有効にしておき、例外を <tt class="docutils literal">ReadWritePaths</tt> にホワイトリスト形式で追加するのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem=</a></p>
</dd>
<dt><tt class="docutils literal">NoNewPrivileges</tt></dt>
<dd><p class="first">プロセスが execve を通して新たに特権を取得することを無効化する。これは、プロセスが特権昇格をできないようにする基本的な方法だ。これにより、攻撃による被害拡大を抑えることができる場合が多い。基本的には指定しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NoNewPrivileges=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NoNewPrivileges=</a></p>
</dd>
<dt><tt class="docutils literal">ProtectProc</tt></dt>
<dd><p class="first">プロセスのメタ情報の可視、不可視を制御する。 <tt class="docutils literal">ProtectProc=noaccess</tt> を指定する場合、他のプロセスの情報を <tt class="docutils literal">/proc</tt> ディレクトリから取得できなくなる。 <tt class="docutils literal">ProtectProc=invisible</tt> を指定する場合、実行ユーザではない他のユーザにより実行されているプロセスの情報は隠され、取得できないようになる。 <tt class="docutils literal">ProtectProc=ptraceable</tt> を指定する場合、 <tt class="docutils literal">ptrace</tt> による他プロセス情報の取得を制限する。 <tt class="docutils literal">ProtectProc=default</tt> を指定する場合、プロセスメタ情報へのアクセス、可視性は特に制限されない。プロセス情報取得は、攻撃者にどのようなサービスが動いているか知る機会を与え、さらなる被害拡大を招きかねない。基本的に他のサービスのプロセス情報を取得する必要があるサービスは限られるだろうから、 <tt class="docutils literal">ProtectProc=invisible</tt> または <tt class="docutils literal">ProtectProc=noaccess</tt> を指定しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectProc=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectProc=</a></p>
</dd>
<dt><tt class="docutils literal">RestrictSUIDSGID</tt></dt>
<dd><p class="first">SUID、SGID 権限をファイルまたはディレクトリに設定するのを拒否する。SUID、SGID は、サービス自体に課せられた特権の制約を無視して、攻撃者が特権を行使するかなり大きなセキュリティホールとなりうる。実行時に SUID、SGID 権限を指定するサービスはほぼないだろうし、あったとしたらそれは代替案を探すべきだろう。なので、基本的には有効化しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=</a></p>
</dd>
<dt><tt class="docutils literal"><span class="pre">RestrictAddressFamilies=~AF_PACKET</span></tt></dt>
<dd><p class="first">デバイスドライバレベルでの生パケット送受信用ソケット作成を制限する。生パケットレベルでの送受信は攻撃者が既存のファイアウォールルールなどを回避しながら、データ送受信を行う手段となりうる。生パケット送受信用ソケット作成を行うサービスはかなり限られるだろうから、指定しておくのが良い。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/socket.2.html">https://man7.org/linux/man-pages/man2/socket.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">SystemCallArchitectures</tt></dt>
<dd><p class="first">後述の <tt class="docutils literal">SystemCallFilter</tt> でフィルタするシステムコールの対象アーキテクチャを指定する。ネイティブのアーキテクチャを対象とする場合は、 <tt class="docutils literal">SystemCallArchitectures=native</tt> と指定する。このオプションを指定しないと、 <tt class="docutils literal">SystemCallFilter</tt> が効かない為、基本的に指定しておくべきだろう。また、ネイティブアーキテクチャ以外を指定する必要が生じる場面は普通なく、下手に範囲を広げるとフィルタリングを回避する穴を作りかねない。 <tt class="docutils literal">SystemCallArchitectures=native</tt> の指定を基本的に入れておくのがいいだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallArchitectures=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallArchitectures=</a></p>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@debug</span></tt></dt>
<dd><p class="first">システムコールの内、デバッグ、パフォーマンス計測機能に関するものの使用を禁じるオプション。もしこれらのシステムコールが呼び出された場合、サービスは SIGSYS シグナルと共に終了することになる。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @debug</tt> で見ることができる。 <tt class="docutils literal">ptrace</tt>、 <tt class="docutils literal">perf_event_open</tt> などが対象。これらのシステムコールは、サービスの情報を詳細に取得し、攻撃者が被害を拡大させるための分析手段として使用できる。基本的に入れておくのが良いだろう。もし、デバッグ機能が必要だとしても、必要なシステムコールだけホワイトリストで追加し直すのが良い。具体的には、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="na">SystemCallFilter</span><span class="o">=</span><span class="s">~@debug</span>
<span class="na">SystemCallFilter</span><span class="o">=</span><span class="s">ptrace</span>
</pre></div></td></tr></table></div>
<p>と書くことで、デバッグ機能のうち、 <tt class="docutils literal">ptrace</tt> システムコールだけを有効化することができる。必要なくなったら無効化しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@swap</span></tt></dt>
<dd><p class="first">システムコールの内、スワップデバイスの有効化、無効化に関するものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @swap</tt> で見ることができる。主に <tt class="docutils literal">swapon</tt>、 <tt class="docutils literal">swapoff</tt> の2つが対象。スワップデバイスの無効化は、メモリ不足を生じさせ、全体的なシステムの不具合を生じさせる手段になる。ファイアウォールなどがメモリ不足で落ちれば、ホストの保護は大幅に低下するだろう。スワップデバイス制御を行うサービスはかなり限られるだろうから、基本的に入れておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@clock</span></tt></dt>
<dd><p class="first">システムコールのうち、システムクロックの制御に関するものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @clock</tt> で見ることができる。主に <tt class="docutils literal">adjtimex</tt>、 <tt class="docutils literal">settimeofday</tt> などが対象。時間に関する判定をバグらせるとセキュリティホールにつながることも多い。クロック制御を行うサービスはかなり限られるだろうから、基本的に入れておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@mount</span></tt></dt>
<dd><p class="first">システムコールのうち、ファイルシステムのマウント制御に関するものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @mount</tt> で見ることができる。主に <tt class="docutils literal">mount</tt>、 <tt class="docutils literal">chroot</tt> などが対象。ファイルシステムのマウントは、ファイルスプーフィングの手段に使える。マウント制御を行うサービスはかなり限られるだろうから、基本的に入れておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@module</span></tt></dt>
<dd><p class="first">システムコールのうち、カーネルモジュールのロード制御に関するものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @module</tt> で見ることができる。主に <tt class="docutils literal">init_module</tt>、 <tt class="docutils literal">delete_module</tt> などが対象。カーネルモジュールのロードを開放することは、攻撃者に被害拡大の手段を与えることも多い。カーネルモジュールのロードが必要なサービスはかなり限られるだろうから、基本的に入れておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@raw-io</span></tt></dt>
<dd><p class="first">システムコールのうち、低レベルの I/O ポートにアクセスするものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> <span class="pre">@raw-io</span></tt> で見ることができる。主に <tt class="docutils literal">ioperm</tt>、 <tt class="docutils literal">pciconfig_read</tt> などが対象。通常は他のシステムコールで代用可能で、カーネルがよしなにやってくれるものを使う方が良い。わざわざ使わないものの使用を解禁し、攻撃者に情報を取得する手段を提供する必要はないため、基本的に入れておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@reboot</span></tt></dt>
<dd><p class="first">システムコールのうち、再起動に関するものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @reboot</tt> で見ることができる。主に <tt class="docutils literal">reboot</tt>、 <tt class="docutils literal">kexec_load</tt> などが対象。再起動を攻撃者に許すと、カーネルモジュールの読み込みをより柔軟にできるようにしたり、再起動直後のセキュリティ保護が万全でない状態を攻撃対象にされかねない。再起動を行うサービスはかなり限られるだろうから、基本的に入れておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">IPAddressAllow</tt> / <tt class="docutils literal">IPAddressDeny</tt></dt>
<dd><p class="first">IP パケットの送受信において、許可するアドレス、拒否するアドレスを指定する。IPv4、IPv6 アドレスを、直接またはレンジで指定できる。 <tt class="docutils literal">IPAddressAllow</tt> が優先となる。特別な識別子がいくつか用意されており、</p>
<ul class="simple">
<li><tt class="docutils literal">any</tt> は <tt class="docutils literal">0.0.0.0/0 <span class="pre">::/0</span></tt> のエイリアス</li>
<li><tt class="docutils literal">localhost</tt> は <tt class="docutils literal">127.0.0.0/8 ::1/128</tt> のエイリアス</li>
<li><tt class="docutils literal"><span class="pre">link-local</span></tt> は <tt class="docutils literal">169.254.0.0/16 <span class="pre">fe80::/64</span></tt> のエイリアス</li>
<li><tt class="docutils literal">multicast</tt> は <tt class="docutils literal">224.0.0.0/4 <span class="pre">ff00::/8</span></tt> のエイリアス</li>
</ul>
<p>としてそれぞれ機能する。ホワイトリストとして使う際は、 <tt class="docutils literal">IPAddressAllow</tt> にリストを指定し、 <tt class="docutils literal">IPAddressDeny=any</tt> も合わせて指定する。ブラックリストの場合は、 <tt class="docutils literal">IPAddressDeny</tt> だけ指定する。使うネットワークが限られているサービスについては、わざわざサービス側に IP フィルタの仕組みを用意しなくても、この機能を使うことでフィルタリングが可能だ。また、攻撃に持続性を持たせるためには、基本的にネットワーク通信は必須であり、その送受信を封じることは強力なセキュリティ保護となる。ネットワーク通信を行わない場合は、 <tt class="docutils literal">IPAddressDeny=any</tt> を指定しておき、リモートアクセスを完全に無効化しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#IPAddressAllow=ADDRESS%5B/PREFIXLENGTH%5D%E2%80%A6">https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#IPAddressAllow=ADDRESS%5B/PREFIXLENGTH%5D%E2%80%A6</a></p>
</dd>
<dt><tt class="docutils literal">DeviceAllow</tt></dt>
<dd><p class="first">デバイスノードに対するアクセス制御を指定する。アクセスを許可するデバイスとその読み込み (<tt class="docutils literal">r</tt>)、書き込み (<tt class="docutils literal">w</tt>)、作成 (<tt class="docutils literal">m</tt>) を許可するかを指定する。物理デバイスに対するアクセスを <tt class="docutils literal">PrivateDevices</tt> で全て無効化している場合は、特に気にしなくていいだろう。デバイスへの直接のアクセスを提供することは、様々なセキュリティ保護を回避しつつ、影響の大きな攻撃を成立させる手段となりうる。もし、物理デバイスに一部でもアクセスが必要な場合は、必要なアクセスのみを指定するのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#DeviceAllow=">https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#DeviceAllow=</a></p>
</dd>
<dt><tt class="docutils literal">NotifyAccess</tt></dt>
<dd><p class="first">systemd のサービスステータス通知へのアクセスを制御する。このオプションはデフォルトで無効化されているため、通常気にすることはないだろう。必要な場合は、必要な範囲のステータス通知だけを受け取るようにしておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.service.html#NotifyAccess=">https://www.freedesktop.org/software/systemd/man/systemd.service.html#NotifyAccess=</a></li>
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/sd_notify.html">https://www.freedesktop.org/software/systemd/man/sd_notify.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@privileged</span></tt></dt>
<dd><p class="first">システムコールのうち、特権が必要なものに関するものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @privileged</tt> で見ることができる。対象には、 <tt class="docutils literal">@swap</tt>、 <tt class="docutils literal">@clock</tt> などを始め、キャパビリティを必要とするものは全部含まれる。流石にキャパビリティを1つ2つ必要とするサービスは普通にあるため、純粋にこのオプションを有効化できない場面もあるだろう。ただ、特権を必要とするシステムコールは影響力が強いからこそ特権が必要となっているため、セキュリティ的にサービスが必要とする特権は把握しておいた方が良いだろう。その意味でも、基本的にはこのオプションを指定しておいて必要となるシステムコールはホワイトリスト形式で指定しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@resources</span></tt></dt>
<dd><p class="first">システムコールのうち、リソースや実行計画の変更に関するものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @resources</tt> で見ることができる。主に <tt class="docutils literal">setrlimit</tt>、 <tt class="docutils literal">setpriority</tt> などが対象。これらのシステムコールによるリソースの占有設定などはシステム全体に悪影響を与える手段となりうる。リソースや実行計画の変更は、重要なサービスのパフォーマンスを確保するのに必要な場合もあるため、完全無効化は難しい場面もあるかもしれないが、基本的に設定しておいて許可するものだけをホワイトリスト形式で指定しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">RestrictRealtime</tt></dt>
<dd><p class="first">リアルタイムスケジューリングの有効化を無効にする。スケジューリングの設定は、CPUリソースを占有することによる他サービスの不調を招く手段となりうる。スケジューリング設定は、重要なサービスのパフォーマンスを確保するのに必要な場合もあるが、もし必要ないなら基本指定しておき、必要なものだけにスケジューリング設定を解放しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictRealtime=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictRealtime=</a></p>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@obsolete</span></tt></dt>
<dd><p class="first">システムコールのうち、使用されないもの、非推奨のもの、未実装のものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @obsolete</tt> で見ることができる。主に <tt class="docutils literal">create_module</tt>、 <tt class="docutils literal">gtty</tt> などが対象。これらのシステムコールを必要とする状況はほぼないだろうから、このオプションは基本指定しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">SystemCallFilter=~@cpu-emulation</span></tt></dt>
<dd><p class="first">システムコールのうち、使用されないもの、非推奨のもの、未実装のものの使用を禁じるオプション。対象のシステムコール一覧は、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> <span class="pre">syscall-filter</span> @obsolete</tt> で見ることができる。主に <tt class="docutils literal">create_module</tt>、 <tt class="docutils literal">gtty</tt> などが対象。これらのシステムコールを必要とする状況はほぼないだろうから、このオプションは基本指定しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/syscalls.2.html">https://man7.org/linux/man-pages/man2/syscalls.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal"><span class="pre">RestrictAddressFamilies=~AF_NETLINK</span></tt></dt>
<dd>Service may allocate netlink sockets (ref: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=</a>)</dd>
<dt><tt class="docutils literal">SupplementaryGroups</tt></dt>
<dd>Service runs with supplementary groups (ref: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SupplementaryGroups=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SupplementaryGroups=</a>)</dd>
<dt><tt class="docutils literal">LockPersonality</tt></dt>
<dd><p class="first">パーソナリティ、つまりカーネル実行ドメインの変更を無効化する。パーソナリティの指定はあまりテストされておらず脆弱性の元になりかねない。またほとんどのサービスで必要となることはないだろうから、基本的に指定しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LockPersonality=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LockPersonality=</a></p>
</dd>
<dt><tt class="docutils literal">MemoryDenyWriteExecute</tt></dt>
<dd><p class="first">書き込み可能かつ実行可能なメモリマッピングを作成したり、既存のメモリマッピングを実行可能になるよう変更することを禁じるオプション。外部からの影響が大きいリモートコード実行の脆弱性は、動的に実行可能コードを埋め込んだり、変更したりできることに起因することが多いため、このオプションはそのような脆弱性をついた攻撃からの保護において有用だ。ただ、JIT 方式を採用しているようなランタイムなどは、その仕組み上そもそも動的に実行可能コードを変更することにより動くため、そのようなランタイムを採用しているサービスではこのオプションは有効化できない。そういう場合以外は基本的に有効化しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#MemoryDenyWriteExecute=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#MemoryDenyWriteExecute=</a></p>
</dd>
<dt><tt class="docutils literal">Delegate</tt></dt>
<dd><p class="first">リソース制御の分割委任を有効化する。適切なリソースの設計と委任設定がされていれば問題ないが、その適切な管理は複雑で難しく、またほとんどのサービスでは必要ないことから、特に有効化する必要はないだろう。また、デフォルトで無効化されているため、基本的に気にする必要はないだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#Delegate=">https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#Delegate=</a></li>
<li><a class="reference external" href="https://systemd.io/CGROUP_DELEGATION/">https://systemd.io/CGROUP_DELEGATION/</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">ProtectHostname</tt></dt>
<dd><p class="first">ホスト名、ドメイン名の名前空間を専用に作成し、さらに変更できないようにする。ホスト名の解決は、基本的にどのドメイン解決より優先される為、ホスト名変更はスプーフィング攻撃などを行う手段として機能しやすい。ホスト名の変更が必要なサービスはかなり限られるだろうから、基本的には有効化しておくのがいいだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHostname=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHostname=</a></p>
</dd>
<dt><tt class="docutils literal"><span class="pre">RestrictAddressFamilies=~AF_UNIX</span></tt></dt>
<dd><p class="first">UNIX ソケットの作成を制限する。UNIX ソケットは外部からのリモートアクセスには直接利用できないが、他のサービスからのデータ通信を、サンドボックス機能などを回避して行う手段となりうる。もしサービスが UNIX ソケット作成を必要としないなら、指定しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/socket.2.html">https://man7.org/linux/man-pages/man2/socket.2.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">ProcSubset</tt></dt>
<dd><p class="first">プロセス管理と情報取得用の <tt class="docutils literal">/proc</tt> ファイルシステムへのアクセスを制限する。 <tt class="docutils literal">ProcSubset=pid</tt> を指定した場合、 <tt class="docutils literal">/proc</tt> にプロセス情報は置かれず PID 毎のディレクトリだけが生成される。 <tt class="docutils literal">ProcSubset=all</tt> を指定した場合、通常の挙動になる。 <tt class="docutils literal">ProtectProc</tt> が指定されていれば、デフォルトの挙動でもそれほど大きな問題にはならないと思われるが、 <tt class="docutils literal">ProcSubset=pid</tt> でサービスが問題なく動くなら、指定しておく分にはその方が良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProcSubset=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProcSubset=</a></p>
</dd>
</dl>
<p>最後に挙動改善機能:</p>
<dl class="docutils">
<dt><tt class="docutils literal">CapabilityBoundingSet</tt></dt>
<dd><p class="first">キャパビリティ境界を設定するオプション。execve 実行時に引き継げるキャパビリティを指定する。任意コード実行のセキュリティホールがあった時に、本体プロセスのキャパビリティが引き継げてしまうと、被害が広がってしまう可能性がある。キャパビリティ境界はデフォルトでは全てのキャパビリティが引き継がれるが、基本的には引き継がなくていいケースが多い。その場合、 <tt class="docutils literal">CapabilityBoundingSet=</tt> と指定することで全てのキャパビリティの引き継ぎを無効化できる。また、引き継ぐ必要がある場合も、引き継ぐ必要があるものをホワイトリストで指定しておいた方が良い。その場合は必要なキャパビリティを明示的に指定しておくのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man7/capabilities.7.html">https://man7.org/linux/man-pages/man7/capabilities.7.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">AmbientCapabilities</tt></dt>
<dd><p class="first">キャパビリティ環境を設定するオプション。キャパビリティ環境は、特権ユーザにより実行されたプロセスでなくても、キャパビリティを与える手段の一つ。特権を行使できるようにすることは攻撃の被害を深刻なものにする可能性があるため、使用を避けるようにするのがよい。デフォルトで指定なしなため、基本的には特に何もしなくても良いと思うが、もしキャパビリティ環境が必要な場合は必要なキャパビリティだけを指定するのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#AmbientCapabilities=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#AmbientCapabilities=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man7/capabilities.7.html">https://man7.org/linux/man-pages/man7/capabilities.7.html</a></li>
</ul>
</dd>
<dt><tt class="docutils literal">RemoveIPC</tt></dt>
<dd><p class="first">サービス停止時ルートユーザ以外の実行ユーザ、グループが持つ IPC オブジェクトを破棄する。IPC オブジェクトを持続的に保持することは、攻撃者が持続的な攻撃を行う手段となりうる。また、サービス終了後も保持し続ける必要はない場合が多い。そのため、基本的には有効化しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RemoveIPC=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RemoveIPC=</a></p>
</dd>
<dt><tt class="docutils literal">UMask</tt></dt>
<dd><p class="first">ファイル作成時の権限マスク。指定されたマスクの部分の権限は取り除かれた状態でファイル、ディレクトリが作成される。デフォルトは <tt class="docutils literal">0022</tt> であり、この場合グループ、その他のユーザの書き込み権限は取り除かれる。この場合、他のユーザからも作成されたファイルの読み取りは可能なため、他のサービスが攻撃された際、攻撃の余波を受ける可能性がある。作成されたファイルを他のユーザと共有する必要がないサービスは多いため、 <tt class="docutils literal">0077</tt> を指定し実行ユーザのみに権限を与えるのが望ましい。また、もしファイルの共有が必要な場合は、共有用のグループで共有の範囲を絞っておくのが良いだろう。その場合は <tt class="docutils literal">0027</tt> でグループのみ参照権限を与えるのが良いだろう。</p>
<p>マニュアル:</p>
<ul class="last simple">
<li><a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#UMask=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#UMask=</a></li>
<li><a class="reference external" href="https://man7.org/linux/man-pages/man2/umask.2.html">https://man7.org/linux/man-pages/man2/umask.2.html</a></li>
</ul>
</dd>
</dl>
</div>
<div class="section" id="auto-id-3">
<h2>その他の有用な機能<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、 <tt class="docutils literal"><span class="pre">systemd-analyze</span> security</tt> では提示されないが、他にも幾つかセキュリティ的に有用な機能がある。それらも紹介しておこう:</p>
<dl class="docutils">
<dt><tt class="docutils literal">PrivateIPC</tt></dt>
<dd>専用の IPC 名前空間を作成し、他のサービスの IPC 空間から隔離するサンドボックス化機能。他のサービスの IPC オブジェクトへの攻撃を避けられる他、名前競合によるクラッシュを避けるという効果も得られる。他のサービスと IPC オブジェクトを共有しないといけないサービスは稀なため、基本的には有効化しておくのが良いだろう。</dd>
<dt><tt class="docutils literal">ReadWritePaths</tt></dt>
<dd><p class="first"><tt class="docutils literal">ProtectSystem</tt> を有効化する場合、一時ディレクトリなどの一部のディレクトリを除いて、ファイルシステムが読み込み専用となる。しかし、実行時データを作成し、書き込むのはサービスの基本的な動作であり、一部ディレクトリに書き込みを許可したい場合はあるだろう。その場合、 <tt class="docutils literal">ReadWritePaths</tt> にホワイトリスト形式でパスを指定することで、そのパスについては書き込みも許可される。また、このパス指定により、サービスが書き込みが起こるパスも明示され分かりやすくなるだろう。基本的には、 <tt class="docutils literal">ProtectSystem</tt> と併用し、書き込みが起こるパスはホワイトリスト管理しておくのが良いだろう。</p>
<p class="last">マニュアル: <a class="reference external" href="https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ReadWritePaths=">https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ReadWritePaths=</a></p>
</dd>
</dl>
<p>今後の systemd バージョンアップで、他にも機能が随時追加、改善されていくだろう。また、サービス自体も機能が改善されていく。それに合わせて定期的に <tt class="docutils literal"><span class="pre">systemd-analyze</span> security</tt> によりセキュリティ機能の見直しを図っていくのが、セキュリティにおいて重要となるだろう。</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、systemd におけるセキュリティ機能の紹介を行った。systemd にはサンドボックス化や機能制限によるセキュリティ向上のための機能と、セキュリティ機能有効化状況の評価機能が備わっている。それらを有効に活用することで、一般のサービスはもちろん、あまり使われていないセキュリティ的に多少不安があるサービスの運用リスクもある程度緩和できるだろう。</p>
<p>なお、昨今は OCI、主に Docker によるサービス管理も主流になりつつあり、systemd でサービスを運用する機会もなくなりつつあるかもしれない。ただ、 Docker などでも事情は同じで、サンドボックス化の強化や機能制限によるセキュリティ向上はやっておいた方がいいだろうし、そうなった時バックにあるものはほぼ systemd のバックで使われてるものと同じになってくる。逆に言えば今回紹介した機能と同じような機能が Docker 側にも用意されている。Docker の場合はある程度サンドボックス化がデフォルトでなされた状態と言えなくもないが、隔離されたコンテナの中に閉じた攻撃は可能であり、また特権利用によるホストの攻撃などの事例もいくつか上がっている。追加の保護施策は有用であり、今回紹介した項目は応用できるだろう。</p>
<p>ここら辺はインターネットに晒されるよく分からない有象無象を動かす人が多くなった時代としては、割と有用だと思うんだが、世間にはあまり知られてなさそうだなあと感じる。 <tt class="docutils literal"><span class="pre">systemd-analyze</span> security</tt> でスコア改善するのは割とゲーム感覚でできておすすめなので、まみんなもぜひやってみてくれという感じ。では、今回はこれで。</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/07/systemd-analyze-security.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/07/systemd-analyze-security.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Ansible の変数を CUE で記述する2023-06-18T08:07:03+09:002023-06-18T08:07:03+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-06-18:/blog/posts/2023/06/ansible-with-cuelang/<p>Ansible や Kubernetes などのオーケストレーションツールでは、タスクやサービスの記述は再利用可能にしておきつつ、設定を別途 …</p><p>Ansible や Kubernetes などのオーケストレーションツールでは、タスクやサービスの記述は再利用可能にしておきつつ、設定を別途記述することである程度カスタマイズできるようにすることがよくある。さらに、設定ファイルは環境毎に一部設定を変えたり、一部を使い回したりと、柔軟に組み合わせて管理がしたいことがある。Ansible や Kubernetes ではそれぞれ専用の機能が用意されている。しかしながら、これらの機能はそこまで設定の組み合わせについてのサポートが手厚いわけではなく、また設定に対してのスキーマ管理などもないため設定が自らの手で管理しきれなくなることが多い。つまり、設定の更新忘れや記述漏れが発生したり、しばらく触らないでいるとどこをどういじればいいか分からなくなるのだ。その結果、デプロイ作業が恣意的なものになりがちで、手元でテストでしても本番でミスるとかいうことにつながりがちだ。</p>
<p>そこで僕は最近、設定ファイルを CUE で記述しマージはそっち任せにして、そこから生成したものを使うということをやってる。今回は、Ansible の設定管理を題材にその方法を紹介する。</p>
<div class="section" id="ansible">
<h2>Ansible と変数<a class="headerlink" href="#ansible" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Ansible 使ってる人には説明の必要もない気がするが、一応前提の共有から。Ansible では、構成の宣言によってデプロイタスクを定義して実行する。この構成の宣言を部分的にグループ化する機能も、Ansible では幾つか提供されている。例えば、Ansible では変数を Jinja テンプレートで使用することで、外部から注入された変数によってタスクを調整することができる。さらに、そういう変数をインベントリグループ毎に設定し、マージする機能も提供している。</p>
<p>例えば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">prod</span><span class="p">:</span>
<span class="w"> </span><span class="nt">children</span><span class="p">:</span>
<span class="w"> </span><span class="nt">public_prod</span><span class="p">:</span>
<span class="w"> </span><span class="nt">hosts</span><span class="p">:</span>
<span class="w"> </span><span class="nt">public-prod001.private</span><span class="p">:</span>
</pre></div></td></tr></table></div>
<p>というようなインベントリを記述すると、 <tt class="docutils literal"><span class="pre">public-prod001.private</span></tt> というホストが <tt class="docutils literal">all</tt>、 <tt class="docutils literal">prod</tt>、 <tt class="docutils literal">public_prod</tt> というグループに所属することになる。このグループそれぞれで変数を設定でき、</p>
<ol class="arabic simple">
<li><tt class="docutils literal">public_prod</tt></li>
<li><tt class="docutils literal">prod</tt></li>
<li><tt class="docutils literal">all</tt></li>
</ol>
<p>の優先順位で、変数が統合されて使われる。これらの変数は、 <tt class="docutils literal">group_vars/</tt> というディレクトリに、 <tt class="docutils literal"><span class="pre"><グループ名>.yml</span></tt> でおけば自動で読み取られる。例えば、 <tt class="docutils literal">group_vars/all.yml</tt> に</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">app_version</span><span class="p">:</span><span class="w"> </span><span class="s">'1.0.0-rc'</span>
<span class="nt">env</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">local</span>
<span class="nt">worker_process</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">100</span>
<span class="nt">resolver</span><span class="p">:</span><span class="w"> </span><span class="s">'8.8.8.8'</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">group_vars/prod.yml</tt> に</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">app_version</span><span class="p">:</span><span class="w"> </span><span class="s">'1.0.0'</span>
<span class="nt">env</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">production</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">group_vars/public_prod.yml</tt> に</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">worker_process</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1024</span>
<span class="nt">public_domain</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">example.com</span>
</pre></div></td></tr></table></div>
<p>などと記述した場合、 <tt class="docutils literal"><span class="pre">public-prod001.private</span></tt> のデプロイ時には、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">app_version</span><span class="p">:</span><span class="w"> </span><span class="s">'1.0.0'</span>
<span class="nt">env</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">production</span>
<span class="nt">worker_process</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">1024</span>
<span class="nt">resolver</span><span class="p">:</span><span class="w"> </span><span class="s">'8.8.8.8'</span>
<span class="nt">public_domain</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">example.com</span>
</pre></div></td></tr></table></div>
<p>という変数群が使用されることになる。この機能を使用することで、開発環境と本番環境で異なる設定を部分的に使用する場合は環境毎にグループを作ってそこの変数で設定、アプリケーション毎に異なる設定を部分的に使用する場合はアプリケーション毎にグループを作ってそこで設定と言ったことができる。</p>
<p>この機能はシンプルで、多くの需要を満たせる反面、ミスに繋がりやすく、またあまりにグループ構成を複雑化しすぎると変数管理が手に負えなくなる面もある。あまり複雑なグループ構成を採用するなと言う話ではあるのだろうが、以下の場面においてより柔軟な設定管理をしたい時はあるだろう:</p>
<ul class="simple">
<li>一部のアプリケーションで共通の設定を使いたい。</li>
<li>ある設定と別の設定を連動させたい。</li>
<li>あるタスクの設定を、一部は環境毎に、一部はアプリケーション毎に設定したい。</li>
</ul>
<p>このような時に、上記のグループ機能を純粋に使うと、かなりグループ構成が複雑になりメンテを楽にするための共通化などがメンテの足を引っ張ることになる時がある。つまり、あるタスクの設定をどこに書き、それがどのホストに対して使われる設定なのか把握するのがかなり困難になるのだ。このような状況だと大規模なリファクタリングなど怖くて行えない。またマージ機能はその性質上、デフォルト値を与えつつ必要な場合は明示的に指定を書くと言ったパターンが頻出するが、その時にあるホストに対して最終的にどの値が使われるかが把握しにくい。</p>
<p>もう一つの課題が、どういう変数が設定ができるかの管理方法だ。Ansible では変数はタスクやテンプレートなどの随所で使用されるわけだが、そうなるとどの変数はどういう値を設定すべきで、どの設定は必須なのかみたいな情報を探すのは割と一苦労で取りこぼしなども出てきてしまう。そういうのを一元的に確認したいことがよくあるのだ。ドキュメントに残すと言うのは一つの方法だが、何の検証もされないドキュメントはタイポなどのミスを生みがちで、また陳腐化もしやすく、ドキュメントを参照しても一元的な確認ができないと言う本末転倒な事態を招きかねない。</p>
<p>僕は一時期これらの課題に対して、JSON schema で設定できる変数をまとめ陳腐化を防ぎつつ、タスクの書き方を工夫することで設定の分離もなんとか管理できるようにして、凌いでいた。ただこれも結構課題があり、特に JSON schema がマージとの相性が悪いこと、マージ機能が貧弱なためにタスクを複雑化させるのは割と本末転倒感があることなどから、代替策を探していた。最近はこれらの課題は大体 CUE 言語使えば解決できることが分かってきたので、CUE で書くようにしている。</p>
</div>
<div class="section" id="cue">
<h2>CUE 言語のモデル<a class="headerlink" href="#cue" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><a class="reference external" href="https://cuelang.org/">CUE 言語</a> は、公式サイトではデータ検証言語と紹介されている。基本的には、YAML や JSON などと同じデータ記述が想定された言語なのだが、データ検証を記述できること、データのマージについて標準的なサポートがあること、豊富なテンプレート記述ができることなどが異なる点だ。特徴的なのが、データ検証とマージに関する機能で、型、制約と値の間に束をモデルとした順序を設け、その順序による階層に違反しないかの検証をデータ検証として採用しつつ、マージもその階層に沿って行う。これにより、柔軟にデータを分割しつつ、結合的で交換的で冪等で安全なデータの結合を実現する。まあ、言葉で説明しても想像しにくいと思うので、実際の例を見ていく。</p>
<p>CUE 言語を試すだけなら、オンラインで <a class="reference external" href="https://cuelang.org/play/">試せる</a>。手元で試したい場合は、<a class="reference external" href="https://cuelang.org/docs/install/">https://cuelang.org/docs/install/</a> を見ながら <tt class="docutils literal">cue</tt> コマンドを入れ、CUE ファイルを作り <tt class="docutils literal">cue eval <span class="pre">--all</span> <file></tt> で CUE ファイルの評価ができる。例えば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span>sample_string: string
sample_string: =~"^[a-z]{3}_[a-z]{2}$"
sample_string: "abc_de"
</pre></div></td></tr></table></div>
<p>は、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span>sample_string: "abc_de"
</pre></div></td></tr></table></div>
<p>に評価される。 <tt class="docutils literal">string</tt> は文字列型、 <tt class="docutils literal"><span class="pre">=~"^[a-z]{3}_[a-z]{2}$"</span></tt> は正規表現制約、 <tt class="docutils literal">"abc_de"</tt> は文字列リテラルになる。これらの間には順序関係があり、 <tt class="docutils literal">string</tt> より <tt class="docutils literal"><span class="pre">=~"^[a-z]{3}_[a-z]{2}$"</span></tt> の方が大きく、 <tt class="docutils literal"><span class="pre">=~"^[a-z]{3}_[a-z]{2}$"</span></tt> より <tt class="docutils literal">"abc_de"</tt> の方が大きい。これらの中で一番大きいのが <tt class="docutils literal">"abc_de"</tt> なため、これが <tt class="docutils literal">sample_string</tt> の値として採用されている。CUE 言語の値のマージにおいては、値間の順序だけが大事なので、以下も同じ結果になる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span>sample_string: =~"^[a-z]{3}_[a-z]{2}$"
sample_string: "abc_de"
sample_string: string
sample_string: "abc_de"
</pre></div></td></tr></table></div>
<p>つまり、どの宣言を先に持ってきても良いし、同じ宣言が複数出てきても良い。これが交換的で冪等であると言うことだ。また、一部を別の変数に括り出すことも可能だ。例えば</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span>sample_string1: sample_string2
sample_string1: sample_string3
sample_string2: string
sample_string2: =~"^abc_[a-z]{2}$"
sample_string3: =~"^[a-z]{3}_de$"
sample_string3: "abc_de"
</pre></div></td></tr></table></div>
<p>は、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span>sample_string1: "abc_de"
sample_string2: =~"^abc_[a-z]{2}$"
sample_string3: "abc_de"
</pre></div></td></tr></table></div>
<p>に評価される。 <tt class="docutils literal"><span class="pre">=~"^abc_[a-z]{2}$"</span></tt> より <tt class="docutils literal">"abc_de"</tt> の方が大きくこれが最大の要素であるため、 <tt class="docutils literal">sample_string1</tt> はこの値になる。マージは結合的であるため、どこを括り出しても結果は変わらない。一方で順序関係による階層が作れないようなものは、データ検証段階で弾かれる。例えば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span>sample_ill: string
sample_ill: int
</pre></div></td></tr></table></div>
<p>は、 <tt class="docutils literal">conflicting values string and int</tt> というエラーが報告され、評価されない。マージにおいて大事なのは、順序による階層に違反してないか、そして順序関係から導かれる最小上界が何であるかだけということになる。ところで今までは最小上界がマージする対象の中に入っている例を見てきたが、必ずしも最小上界は記述された値の中にあるとは限らない。例えば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj1: sample_obj2
sample_obj1: sample_obj3
sample_obj2: sample_string1: "str1"
sample_obj2: sample_string2: "str2"
sample_obj3: sample_string2: string
sample_obj3: sample_string3: "str3"
</pre></div></td></tr></table></div>
<p>は、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj1: {
sample_string1: "str1"
sample_string2: "str2"
sample_string3: "str3"
}
sample_obj2: {
sample_string1: "str1"
sample_string2: "str2"
}
sample_obj3: {
sample_string2: string
sample_string3: "str3"
}
</pre></div></td></tr></table></div>
<p>に評価される。CUE 言語はもちろん構造体をサポートしている。 <tt class="docutils literal">a: b: string</tt> という記述は <tt class="docutils literal">a: { b: string }</tt> と言う記述の略記であり、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj1: sample_obj2
sample_obj1: sample_obj3
sample_obj2: sample_string1: "str1"
sample_obj2: sample_string2: "str2"
sample_obj3: sample_string2: string
sample_obj3: sample_string3: "str3"
</pre></div></td></tr></table></div>
<p>は、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span>{
sample_obj1: sample_obj2
sample_obj1: sample_obj3
sample_obj2: { sample_string1: "str1" }
sample_obj2: { sample_string2: "str2" }
sample_obj3: { sample_string2: string }
sample_obj3: { sample_string3: "str3" }
}
</pre></div></td></tr></table></div>
<p>と記述するのと等しい。つまり、 <tt class="docutils literal">sample_obj1</tt> は <tt class="docutils literal">{ sample_string1: "str1" }</tt>、 <tt class="docutils literal">{ sample_string2: "str2" }</tt>、 <tt class="docutils literal">{ sample_string2: string }</tt>、 <tt class="docutils literal">{ sample_string3: "str3" }</tt> の最小上界を値に持つと言うことであり、その値が <tt class="docutils literal">{ sample_string1: "str1", sample_string2: "str2", sample_string3: "str3" }</tt> であるということになる。構造体の順序については少々複雑なので後で詳しく触れるが、基本的にはこのようにフィールドそれぞれをマージするような挙動をする。</p>
<p>この機能はかなり強力であり、今回のように一部の値を先行して埋めその際データ検証が通るようにしたい、複数の部分的なスキーマを統合したいなどといったデータ記述のマージに関する複雑な需要がありかつデータ検証も行いたいような場合にかなり効力を発揮する。さらに CUE 言語には、フィールドの内包表記、文字列に対するパラメータの差し込み、条件分岐といった多少複雑なテンプレート機能をサポートしており、これもデータ記述の統合に力を貸してくれるだろう。詳細は、 <a class="reference external" href="https://cuelang.org/docs/tutorials/tour/expressions/">CUE 言語の式に関するドキュメント</a> を見てもらうのがいいだろう。</p>
<p>さて、データ記述が分けられるとくれば、ファイル分割によりファイルシステムに沿ったデータ記述の断片管理をしたいというのも需要の一つだ。CUE 言語では、ディレクトリレイアウトと連動可能なモジュールシステムを備えており、ファイル分割もサポートしている。ディレクトリレイアウトとモジュールシステムを連動させるには、まずそのレイアウトのルートとなるディレクトリにモジュールに関する宣言を行う必要がある。これは、 <tt class="docutils literal">cue</tt> コマンドを利用して行うことができ、レイアウトのルートとなるディレクトリに移動し、以下のコマンドを実行することで宣言できる:</p>
<pre class="literal-block">
cue mod init [モジュール名]
</pre>
<p>モジュール名は、そのモジュールに所属するパッケージのルートパスとなる識別子で、ドメインとオプションでパスを指定する。例えば、 <tt class="docutils literal">mizunashi.work/pkg</tt> といった感じだ。手元で試すだけならドメインは所有している必要はなく実在している必要もない。ひとまず他のモジュールと被らないようなドメイン名であれば問題ないだろう。さて、モジュールの宣言を行うと、 <tt class="docutils literal">cue.mod</tt> というディレクトリが作られ、そこにモジュールに関するファイル群が配置されることになる。それぞれ</p>
<ul class="simple">
<li><tt class="docutils literal">module.cue</tt> ファイルはモジュールに関する情報が宣言されるファイルで、モジュール名が記述されることになる。</li>
<li><tt class="docutils literal">pkg</tt> ディレクトリは、外部モジュールが置かれるディレクトリで、ここに他のモジュールをダウンロードしてそのモジュール名に合わせて配置すると、そのモジュールも読み込めるようになる。</li>
<li><tt class="docutils literal">usr</tt> ディレクトリは使ったことがないのでよく分からないが、使用する CUE 言語のユーザ定義拡張などを置く場所のようだ。</li>
</ul>
<p>この <tt class="docutils literal">cue.mod</tt> が置かれたディレクトリについて、 <tt class="docutils literal">a/b/sample.cue</tt> といったファイルを以下の内容で作る:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span>package sample
sample_string: "abc"
</pre></div></td></tr></table></div>
<p>この時、モジュール名が <tt class="docutils literal">mizunashi.work/pkg</tt> であれば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span>import "mizunashi.work/pkg/a/b:sample"
sample_obj: imported: sample
</pre></div></td></tr></table></div>
<p>は</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: {
imported: {
sample_string: "abc"
}
}
</pre></div></td></tr></table></div>
<p>に評価される。基本的にパス名にコロン区切りでパッケージ名を繋げることで、そのパッケージのパスになる。なお、パッケージ自体を複数ファイルに分割することもでき、 <tt class="docutils literal">a/sample/obj1.cue</tt> を</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span>package sample
sample_string2: "abc2"
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">a/sample/obj2.cue</tt> を</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span>package sample
sample_string3: "abc3"
</pre></div></td></tr></table></div>
<p>とすると、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span>import "mizunashi.work/pkg/a/sample"
sample_obj: imported: sample
</pre></div></td></tr></table></div>
<p>は</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: {
imported: {
sample_string2: "abc2"
sample_string3: "abc3"
}
}
</pre></div></td></tr></table></div>
<p>に評価される。この機能により、基本的に CUE 言語にファイル分割も任せれば、特に Ansible などの変数の利用側でファイル分割の機能を利用しなくてもよくなり、より柔軟で安全なデータ記述管理ができる。</p>
</div>
<div class="section" id="auto-id-4">
<h2>Ansible での利用<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>では、この CUE を使って僕が Ansible の変数をどうやって管理しているかも紹介していこう。実例は、<a class="reference external" href="https://github.com/mizunashi-mana/mizunashi-work-playbook">https://github.com/mizunashi-mana/mizunashi-work-playbook</a> にある。</p>
<p>Ansible での CUE による変数管理の場合、僕は基本的に以下のような構成にするようにしている:</p>
<ul class="simple">
<li>インベントリディレクトリを CUE モジュールのルートとする。</li>
<li><dl class="first docutils">
<dt>ロール一つ一つをパッケージとするそのロールのスキーマを <tt class="docutils literal"><span class="pre">roles/*/schema.cue</span></tt> に書く。</dt>
<dd><ul class="first last">
<li>例えば、 <tt class="docutils literal">roles/node_exporter</tt> という Node Exporter のインストールロールがある時、 <tt class="docutils literal">roles/node_exporter/schema.cue</tt> に <tt class="docutils literal">node_exporter</tt> パッケージとして、そのロールで使用する変数を記述する。</li>
<li>記述例は、<a class="reference external" href="https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/389cfd78428dc8ede6fa941d7e2014fb47d3a136/roles/node_exporter/schema.cue">https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/389cfd78428dc8ede6fa941d7e2014fb47d3a136/roles/node_exporter/schema.cue</a> とかを参照してもらうのが良いだろう。</li>
</ul>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>インベントリグループ毎の変数のスキーマを、 <tt class="docutils literal"><span class="pre">schemas/*.cue</span></tt> にグループの名前に合わせたパッケージを書く。</dt>
<dd><ul class="first last">
<li>必ずしもこれはグループを発行する必要はないし、グループに対応させる必要もない。が、グループに対応させておくと分かりやすい。</li>
<li>記述例は、<a class="reference external" href="https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/389cfd78428dc8ede6fa941d7e2014fb47d3a136/roles/node_exporter/schema.cue">https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/389cfd78428dc8ede6fa941d7e2014fb47d3a136/roles/node_exporter/schema.cue</a> とかを参照してもらうのが良いだろう。</li>
<li>基本的には、そのグループでプロビジョンが必要なロールのスキーマを読み込むだけで良い。上の記述例がどういう意味論を持つかは後ほど詳しく見る。</li>
</ul>
</dd>
</dl>
</li>
<li>その他共通化したいスキーマや設定などは適宜ディレクトリを作ってパッケージを作る。</li>
<li><dl class="first docutils">
<dt>グループ変数、ホスト変数生成用の CUE ファイルを、生成先のディレクトリに生成先の名前に合わせて作る。</dt>
<dd><ul class="first last">
<li>上で作ったスキーマを適宜読み込み、グループに対しての変数を設定していく</li>
<li>記述例は、<a class="reference external" href="https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/389cfd78428dc8ede6fa941d7e2014fb47d3a136/group_vars/internal_vagrant.cue">https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/389cfd78428dc8ede6fa941d7e2014fb47d3a136/group_vars/internal_vagrant.cue</a> とかを参照してもらうのが良いだろう。</li>
<li>上の記述例では、スキーマにない変数が間違って設定されないような工夫を施している。この記述例がどう言う意味論を持つかは後ほど詳しく見る。</li>
</ul>
</dd>
</dl>
</li>
</ul>
<p>そして、 <tt class="docutils literal">cue export <span class="pre">--out</span> yaml group_vars/sample.cue <span class="pre">--outfile</span> group_vars/sample.yml</tt> といった具合にグループ変数、ホスト変数を生成する。基本生成するのは末端のグループだけで、後のグループの変数は CUE 側でマージしておけば、適切に共通化部分をコントロールでき、また最終的に適用される変数が分かりやすい。</p>
<p>ただ、このままだと対応できないものが一つだけあって、それが Ansible Vault だ。Ansible Vault は、暗号化済みファイルの注入か YAML カスタムタグでの注入しかサポートしてないっぽくて、CUE 言語では直接の対応はできない。そこで、僕は純粋に CUE 言語で対応するのはやめて、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span>sample_vault: "__ansible_vault": """
$ANSIBLE_VAULT;1.1;AES256
...
"""
</pre></div></td></tr></table></div>
<p>みたいな入力が与えられた時、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">sample_vault</span><span class="p">:</span><span class="w"> </span><span class="kt">!vault</span><span class="w"> </span><span class="p p-Indicator">|</span>
<span class="w"> </span><span class="no">$ANSIBLE_VAULT;1.1;AES256</span>
<span class="w"> </span><span class="no">...</span>
</pre></div></td></tr></table></div>
<p>に変換する <a class="reference external" href="https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/389cfd78428dc8ede6fa941d7e2014fb47d3a136/cue_compiler/compiler.py">簡単な Python スクリプト</a> を書いている。そこまで大したことはしてなくて、 <tt class="docutils literal">cue export</tt> で一旦上の CUE を YAML に変換した後、 <tt class="docutils literal">"__ansible_vault": ...</tt> みたいなオブジェクトを探して <tt class="docutils literal">!vault ...</tt> に変換し、YAML として再度出力してるというだけだ。ここら辺も CUE だけで完結できればかっこいいんだろうが、まあとりあえずこれで困ってない。他にいいやり方知ってたら教えて欲しい。</p>
</div>
<div class="section" id="auto-id-5">
<h2>CUE の構造体とその開閉<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、基本上記のような構成で、Ansible の変数をスキーマベースでファイル分割を怯えずに管理できる。ただ、幾つか CUE の構造体についてさらに知っておくと色々やりやすくなるので、最後にその点を触れておく。</p>
<p>まず、 CUE の構造体には開いているか閉じているかという属性がある。開いている構造体は、自身が含んでいないフィールドを持つ構造体でも、自身が含んでいるフィールドのみ互換性があれば順序がつく。つまり、 <tt class="docutils literal">{ a: int }</tt> という開いた構造体があった場合、 <tt class="docutils literal">{ a: 1, b: string }</tt> といった <tt class="docutils literal">a</tt> フィールドは互換性があり、さらに <tt class="docutils literal">b</tt> というフィールドが追加されているような構造体との間に順序がつく。このため、マージの際フィールドを新たに追加することが許可される。しかし、閉じた構造体はこういうことは許されない。つまり、 <tt class="docutils literal">close({ a: int })</tt> と <tt class="docutils literal">{ a: 1, b: string }</tt> の間には順序がつかず、同じ階層にも所属できない。ここで、 <tt class="docutils literal">close({ a: int })</tt> は <tt class="docutils literal">{ a: int }</tt> の閉じたバージョンだ。実際に</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span>sample_ill: close({ a: int })
sample_ill: { a: 1, b: string }
</pre></div></td></tr></table></div>
<p>は評価されず、 <tt class="docutils literal">sample_ill.b: field not allowed</tt> というエラーが出る。閉じた構造体は、自身が持つフィールドと互換性のある範囲しかマージができない。例えば上記の例を逆に</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: close({ a: 1, b: string })
sample_obj: { a: int }
</pre></div></td></tr></table></div>
<p>とすると、これは評価され、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: {
a: 1
b: string
}
</pre></div></td></tr></table></div>
<p>という結果になる。この閉じた構造体を使うことで、スキーマで定義されたフィールド以外の宣言がないことを検証できる。これは、更新忘れなどを防ぐのに役にたつ。</p>
<p>ここで、何点か注意して置く必要がある。一つ目は、宣言された構造体が開いたものになるか、閉じたものになるかの条件だ。基本的に <tt class="docutils literal">{}</tt> で囲まれて宣言された構造体は開いた構造体になり、 <tt class="docutils literal">close</tt> でさらに囲むと閉じた構造体になる。ただし、宣言の仕方によっては <tt class="docutils literal">close</tt> を書かなくてもデフォルトで閉じた構造体になることがある。それが、秘匿フィールド (hidden field) での宣言の場合だ。秘匿フィールドは、 <tt class="docutils literal">#</tt> から始まるフィールドで、このフィールドは最終結果からは除外される。例えば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span>#sample_hidden: 1
sample_str: "str"
</pre></div></td></tr></table></div>
<p>は、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span>sample_str: "str"
</pre></div></td></tr></table></div>
<p>に評価される。秘匿フィールドではなく、最終結果に含めるフィールドとして宣言するには、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span>"#sample_int": 1
sample_str: "str"
</pre></div></td></tr></table></div>
<p>というように、クオートで囲む必要がある。秘匿フィールドは、スキーマの宣言や、最終結果に含めたくないが CUE 上での共通化のための宣言を行うために便利だ。さて、この秘匿フィールドは、基本宣言がそれだけで完結していることが多いため、デフォルトで再帰的に構造体が閉じるようになっている。実際に試してみると、例えば</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span>#sample_hidden: a: 1
sample_obj: #sample_hidden
sample_obj: b: 2
</pre></div></td></tr></table></div>
<p>は、評価されず、 <tt class="docutils literal">sample_obj.b: field not allowed</tt> というエラーが出る。注意したいのは、秘匿フィールドの宣言自体では、開いた構造体が使えるということだ。例えば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span>#sample_hidden: a: 1
#sample_hidden: b: 2
sample_obj: #sample_hidden
</pre></div></td></tr></table></div>
<p>は、問題なく</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: {
a: 1
b: 2
}
</pre></div></td></tr></table></div>
<p>と評価される。あくまで秘匿フィールドを使用する際には閉じた構造体として扱われるということだ。このことに注意しながら、秘匿フィールドを交えてデータ記述を行うと、より柔軟なデータ記述ができるだろう。</p>
<p>もう一つの注意点は、構造体のマージには実は幾つか構文があり、それぞれ異なる意味論を持っているということだ。今まで基本的に使ってきた</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: { a: 1, b: 2 }
sample_obj: { b: int, c: 3 }
</pre></div></td></tr></table></div>
<p>という記述は、以下と等価になる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: { a: 1, b: 2 } & { b: int, c: 3 }
</pre></div></td></tr></table></div>
<p>これは、今までのマージが、マージ対象の最小上界であるということが分かりやすい。もちろん、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: close({ a: 1, b: int })
sample_obj: { b: 2 }
</pre></div></td></tr></table></div>
<p>も</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: close({ a: 1, b: int }) & { b: 2 }
</pre></div></td></tr></table></div>
<p>と記述できる。それに対して、構造体のマージは埋め込み (embedding) と呼ばれる他の意味論を持つ構文も用意されている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: {
close({ a: 1, b: int })
b: 2
{ c: 3 }
}
</pre></div></td></tr></table></div>
<p>この記述を評価すると、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: {
a: 1
b: 2
c: 3
}
</pre></div></td></tr></table></div>
<p>になる。これは、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span>sample_obj: close({ a: 1, b: int }) & {
b: 2
c: 3
}
</pre></div></td></tr></table></div>
<p>が評価されずエラーになるのと対照的だ。埋め込みは、マージの対象に対して単に最小上界を取るのではなく、構造体のフィールドを全て展開してからマージを行う。このため、閉じた構造体も開いた構造体と同じようにマージされる。ただし、マージ対象の中に一つでも閉じた構造体がある場合、マージされた構造体も閉じた構造体になる。これらを同じ構文だと思うと色々ハマるので注意が必要だが、これらの構文をうまく使い分けできれば、柔軟なデータ管理ができるだろう。</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、CUE 言語の紹介と、それを Ansible の変数管理に活用する構成例を紹介した。最初の頃は構造体やモジュールの仕様につまづき、色々苦労もしたが、今は結構色々助かってて安心して変数を増やしたり削除したりできるようになったし、出力される変数のファイル自体は1ファイルなので、変数の差分なども見やすくなって色々重宝してる。まだ色々手探りなところもあるものの、現状そうつまづくことはないかなあという感じで、後の懸念点は安定性がどんくらいなのかなあということぐらいか。ま、興味があれば使ってみて欲しい。</p>
<p>では、今回はこれで。</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/06/ansible-with-cuelang.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/06/ansible-with-cuelang.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>nftables のログを JSON で吐く2023-05-21T12:12:17+09:002023-05-21T12:12:17+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-05-21:/blog/posts/2023/05/nftables-json-logging/<p>Linux でのファイアウォールが nftables になってからかなり経つ。iptables フロントエンドよりも分かりやすい設定ファイルと設定 …</p><p>Linux でのファイアウォールが nftables になってからかなり経つ。iptables フロントエンドよりも分かりやすい設定ファイルと設定の永続化方法も用意され、カーネル側で単純なファイアウォールを組むだけなら nftables 単体で十分になった。</p>
<p>さて、nftables にはパケットフィルタリングの機能に加えて、パケットのロギングをする機能が組み込まれている。これは iptables 時代からある機能で、パケットフィルタの動作監視や、パケット流入の状況監視などに使える。標準では、このログはカーネルログに独自の形式で吐かれるが、フォーマッタや出力先は調整できる機能が入っている。今回は、この機能を ulogd を通して使い、JSON 形式で別ファイルにパケットログを出す方法を紹介する。</p>
<div class="section" id="nftables">
<h2>nftables とログ出力<a class="headerlink" href="#nftables" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>nftables の基本的な使い方は、 <a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2019/09/nftables-on-debian/">昔</a> 書いたので、そっちを参照してもらうのがいいだろう。僕が使ってる ruleset は <a class="reference external" href="https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/04d0f8fc5701ef400d543bfa91bc45c4f056be4e/roles/nftables/files/etc/nftables.conf">https://github.com/mizunashi-mana/mizunashi-work-playbook/blob/04d0f8fc5701ef400d543bfa91bc45c4f056be4e/roles/nftables/files/etc/nftables.conf</a> にある。良かったら、参考にどうぞ。今回は、ログ出力に関わる部分のみにとどめた nftables の使い方だけを見ていくことにする。</p>
<p>nftables には、ログ出力用の log statement があり、matcher / control flow と合わせて使うことができる。例えば、TCP 宛先ポート 80 のパケットを、1分に1エントリーのレートでログ出力するには、次のような文を入れる:</p>
<pre class="literal-block">
tcp dport 80 limit rate 1/minute log prefix "[NFTABLES HTTP PKT]: " continue;
</pre>
<p>input filter に仕込むと該当のパケットが来た場合、カーネルログに次のようなメッセージが出る:</p>
<pre class="literal-block">
May 21 08:01:58 internal kernel: [55242.749774] [NFTABLES HTTP PKT]: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:86:dd SRC=fde4:8dba:82e1:1006:0000:0000:0000:1001 DST=fde4:8dba:82e1:1006:0000:0000:0000:1001 LEN=401 TC=0 HOPLIMIT=64 FLOWLBL=815899 PROTO=TCP SPT=59840 DPT=80 WINDOW=512 RES=0x00 ACK PSH URGP=0
</pre>
<p>基本的にカーネルログへ出る形式は、 <tt class="docutils literal"><span class="pre">フィールド名[=値]</span></tt> という感じ。prefix でどのパケットのログかを見分けることになる。flood 対策のログとかは全部流してしまうと、DoS 対策のフィルターのログでディスクが詰まって DoS が成立してしまうということになりかねないので、基本 rate limiter とセットがいいだろう。今回は紹介しないが、counter 機能を使えば、数は正確に計測ができる。ログ出力と付き合わせれば、ある程度監視が効くようになるだろう。</p>
</div>
<div class="section" id="ulogd">
<h2>ulogd で出力先を変更する<a class="headerlink" href="#ulogd" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、監視には分析環境の整備とデータ整理が必要になる。特にデータ処理において、独自の形式のログだと色々取り扱いにくい。パケット監視にしても、やっぱりプロトコルの種類、送信元アドレス、宛先ポートなど、監視したい項目は色々あるだろう。そこら辺に関して、クエリが書けるようにはしときたい。そのような需要に対応するため、nftables のログは出力先の変更やフォーマットの変更に対応している。その中でも手軽な方法は、 <a class="reference external" href="https://www.netfilter.org/projects/ulogd/">ulogd</a> を使う方法だ。</p>
<p>まずは、 <a class="reference external" href="https://www.netfilter.org/projects/ulogd/">ulogd</a> をインストールする。Debian では標準のパッケージとして提供されていて、 <tt class="docutils literal">apt</tt> で入る:</p>
<pre class="literal-block">
apt install ulogd2
</pre>
<p>後、JSON 形式での出力をサポートするため、JSON モジュールもインストールしておく:</p>
<pre class="literal-block">
apt install ulogd2-json
</pre>
<p><tt class="docutils literal">ulogd</tt> の設定ファイルは <tt class="docutils literal">/etc/ulogd.conf</tt> にある。色々プラグインが用意されており、syslog や Graphite への出力などもサポートしているようだ。プラグインの種類は入力、フィルター、出力の3種類がある。今回は、</p>
<ul class="simple">
<li><dl class="first docutils">
<dt>入力</dt>
<dd><ul class="first last">
<li>NFLOG: nftables での基本的なパケットログ入力元。ま、基本入力はこれで良い。</li>
</ul>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>フィルター</dt>
<dd><ul class="first last">
<li>BASE: 基本的なパケット情報をログに含める。</li>
<li>IFINDEX: ネットワークインターフェースをインデックスではなく名前でログる。</li>
<li>HWHDR: MACアドレスを文字列形式でログる。</li>
<li>IP2STR: IPアドレスを文字列形式でログる。</li>
</ul>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>出力</dt>
<dd><ul class="first last">
<li>JSON: JSON 形式でファイルに出力する。</li>
</ul>
</dd>
</dl>
</li>
</ul>
<p>を使っていく。他のプラグインについては、<a class="reference external" href="https://git.netfilter.org/ulogd2/tree/doc/ulogd.sgml">https://git.netfilter.org/ulogd2/tree/doc/ulogd.sgml</a> を参照すると良いだろう。まず、使うプラグインを有効化しておく。 <tt class="docutils literal">/etc/ulogd.conf</tt> の上部にある、plugin の定義で該当する箇所をコメントアウトしておく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div><pre><span></span><span class="na">plugin</span><span class="o">=</span><span class="s">"/usr/lib/x86_64-linux-gnu/ulogd/ulogd_inppkt_NFLOG.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_inppkt_ULOG.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_inppkt_UNIXSOCK.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_inpflow_NFCT.so"</span>
<span class="na">plugin</span><span class="o">=</span><span class="s">"/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_IFINDEX.so"</span>
<span class="na">plugin</span><span class="o">=</span><span class="s">"/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_IP2STR.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_IP2BIN.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_IP2HBIN.so"</span>
<span class="na">plugin</span><span class="o">=</span><span class="s">"/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_PRINTPKT.so"</span>
<span class="na">plugin</span><span class="o">=</span><span class="s">"/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_HWHDR.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_PRINTFLOW.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_filter_MARK.so"</span>
<span class="na">plugin</span><span class="o">=</span><span class="s">"/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_LOGEMU.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_SYSLOG.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_XML.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_SQLITE3.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_GPRINT.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_NACCT.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_PCAP.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_PGSQL.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_MYSQL.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_DBI.so"</span>
<span class="na">plugin</span><span class="o">=</span><span class="s">"/usr/lib/x86_64-linux-gnu/ulogd/ulogd_raw2packet_BASE.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_inpflow_NFACCT.so"</span>
<span class="c1">#plugin="/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_GRAPHITE.so"</span>
<span class="na">plugin</span><span class="o">=</span><span class="s">"/usr/lib/x86_64-linux-gnu/ulogd/ulogd_output_JSON.so"</span>
</pre></div></td></tr></table></div>
<p>次に、入力先と出力先の設定をする:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">[log17]</span>
<span class="na">group</span><span class="o">=</span><span class="s">17</span>
<span class="k">[json17]</span>
<span class="na">sync</span><span class="o">=</span><span class="s">1</span>
<span class="na">file</span><span class="o">=</span><span class="s">"/var/log/ulog/nftables.log"</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">log17</tt> は入力元の設定、 <tt class="docutils literal">json17</tt> は出力先の設定になる。入力側の <tt class="docutils literal">group</tt> は nftables 側で設定するグループに合わせる。nftables 側では log statement に設定する:</p>
<pre class="literal-block">
tcp dport 80 limit rate 1/minute log prefix "[NFTABLES HTTP PKT]" group 17 continue;
</pre>
<p>group はそれぞれの statement 毎に指定可能で、ulogd 側でも複数のグループをそれぞれ扱うことができる。JSON 出力の設定には、出力先のファイルパスの指定 (<tt class="docutils literal">file</tt>) と同期出力するかの設定 (<tt class="docutils literal">sync</tt>)、他にもいくつか設定ができる。同期出力するかは、ログ出力を同期的に行う設定で、その分パケット処理のパフォーマンスは劣化するが、ログの反映が早くなる。</p>
<p>これらのプラグイン設定をもとに、以下のようにログ出力のスタックを組むことができる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="na">stack</span><span class="o">=</span><span class="s">log17:NFLOG,base1:BASE,ifi1:IFINDEX,ip2str1:IP2STR,mac2str1:HWHDR,json17:JSON</span>
</pre></div></td></tr></table></div>
<p>これにより、 <tt class="docutils literal">/var/log/ulog/nftables.log</tt> に以下のようなログが載るようになる:</p>
<pre class="literal-block">
{"timestamp": "2023-05-21T10:54:05.058650", "dvc": "Netfilter", "raw.pktlen": 80, "raw.pktcount": 1, "oob.prefix": "[NFTABLES HTTP PKT]", "oob.time.sec": 1684666445, "oob.time.usec": 58650, "oob.mark": 0, "oob.ifindex_in": 4, "oob.hook": 1, "raw.mac_len": 14, "oob.family": 10, "oob.protocol": 34525, "raw.label": 0, "raw.type": 1, "raw.mac.addrlen": 6, "ip.protocol": 6, "ip6.payloadlen": 40, "ip6.priority": 0, "ip6.flowlabel": 960112, "ip6.hoplimit": 64, "ip6.nexthdr": 6, "src_port": 52938, "dest_port": 80, "tcp.seq": 3860706922, "tcp.ackseq": 0, "tcp.window": 64800, "tcp.offset": 0, "tcp.reserved": 0, "tcp.urg": 0, "tcp.ack": 0, "tcp.psh": 0, "tcp.rst": 0, "tcp.syn": 1, "tcp.fin": 0, "tcp.res1": 0, "tcp.res2": 0, "tcp.csum": 50192, "oob.in": "eth2", "oob.out": "", "src_ip": "fde4:8dba:82e1:1006::1001", "dest_ip": "fde4:8dba:82e1:1006::1002", "mac.saddr.str": "08:00:27:5b:f8:27", "mac.daddr.str": "08:00:27:2d:64:2b", "mac.str": "08:00:27:2d:64:2b:08:00:27:5b:f8:27:86:dd"}
</pre>
<p>後は適当にログコレクタで JSON パースして、分析環境に上げておけば、パケットの監視を行うことができる。</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、今回は nftables のログを JSON で別ファイルに出力する方法だった。ulogd インストールして、単純な設定するだけでできるので、割と簡単。</p>
<p>僕のサーバではとりあえずフィルタのログと、後出力パケットを limit かけてログって fluent-bit でパースして ElasticSearch に上げてる。で、プロトコル種別、宛先ポート番号とか別での時間帯によるパケット数推移とかを見てる。出力パケットからマルウェア検知とかできることもあるし、まあログを解析しやすいようにしておくと何かと便利。ま、今時 nftables 直接触ってる人も少ないと思うが、何か参考になれば。では、今回はこれで。</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/05/nftables-json-logging.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/05/nftables-json-logging.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>ACME 対応 Private CA を手軽に立てる2023-05-19T10:55:20+09:002023-05-19T10:55:20+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-05-19:/blog/posts/2023/05/operating-private-ca-with-acme/<p>今日のネットワーク通信では、様々な中継ポイントを介すことが多い。これにより、様々な繋がりを作ることができるようになっている。しかしその反面、中継ポイントには様々な運用者が挟まることになり、盗聴や改竄といった不正 …</p><p>今日のネットワーク通信では、様々な中継ポイントを介すことが多い。これにより、様々な繋がりを作ることができるようになっている。しかしその反面、中継ポイントには様々な運用者が挟まることになり、盗聴や改竄といった不正を行いやすい状況になっている。そのため、通信の秘匿化、接続相手の認証が重要になる。そのような状況で、覇権を握っているのが TLS という仕組みになる。</p>
<p>TLS 通信では、大まかには、接続先から提供される証明書が妥当なものかを検証し、その情報を元に暗号通信のための情報を秘密裏に共有し、秘匿化された暗号通信路を確保する。証明書の検証が接続相手の認証に相当し、その後の暗号通信路の確保が通信の秘匿化に対応することになる。今回は、このうち証明書の検証の部分のみを扱っていく。認証は事前の何らかの情報共有が必要になる。単純にはそれぞれの接続先に対して認証情報を事前に確保しておくと認証は行えるが、今日の接続先が無数にある状況では、認証情報の管理方式に問題が出てくる。そこで、TLS 通信では、一部の認証局と呼ばれる機関の認証情報のみを事前に共有しておき、接続先は証明書を事前に認証局に認証してもらった上で交付し、認証局の認証部分を検証するようにすることで共有する認証情報を抑えつつ、柔軟で拡張性のある暗号通信の仕組みを提供する。</p>
<p>さて、TLS 通信の規格は全て公開されており、もちろん認証局も自分で開設することが可能である。認証局からの証明書の発行は元来は手動操作だったが、昨今は発行操作が規格化され、より認証局の運用は簡単なものになっている。今回はこの ACME というプロトコルで規格化された証明書発行フローの紹介と、そのフローに対応した認証局の開設、運用を caddy という Web サーバで行う方法を紹介する。</p>
<div class="section" id="tls-ca">
<h2>TLS 証明書と CA<a class="headerlink" href="#tls-ca" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>TLS 通信における接続相手の認証は、サーバから送られたサーバ認証証明書データとその証明書データを使って作られた署名データによって行われる。これはデジタル署名の応用によるもので、TLS 1.3 では署名アルゴリズムとして RSA / ECDSA / EdDSA などの幾つかのアルゴリズムが使えるが、これらのアルゴリズムには共通して</p>
<ul class="simple">
<li>公開鍵、秘密鍵のペアを発行し、</li>
<li>秘密鍵から生成した署名データが公開鍵で検証可能、すなわち署名データが必ず元データから対となる秘密鍵で生成したものであることを判定でき、</li>
<li>公開鍵からは秘密鍵が現実的に類推不可能である</li>
</ul>
<p>という特徴がある。この特徴を利用することで、公開鍵を証明書データに入れておき、証明書データの公開鍵と対となる秘密鍵でクライアントからのリクエストを署名して署名データとして送ることで、通信相手を認証することができると言うわけだ。ただ、これには前提として、送られてきた証明書データが送り主のものであることをクライアントが保証できる必要がある。</p>
<p>単純にはこれには現存する全ての証明書をクライアントが把握していれば良いわけだが、現状 TLS が普及し、無数のサーバが存在する中で、全ての証明書を把握することはリソース的に難しいし、また管理するリソースが増えることで安全性の欠落を招きかねない。そこで重要となるのが PKI、日本語で公開鍵基盤と呼ばれる仕組みである。PKI とはまさに、公開鍵がその持ち主のものであることを保証する仕組みのことを指す総称である。TLS において最も広く用いられている PKI 規格として X.509 PKI <a class="footnote-reference" href="#rfc-5280" id="auto-id-1">[1]</a> がある。X.509 では、PKI の機能を証明書の連鎖によって実現する。つまり、ある通信先の識別子が書かれた証明書を別の秘密鍵で署名しておき、そちらの対となる公開鍵をクライアントが知れるようにしておくことで、署名された証明書そのものは通信の際に取得しつつ、証明書に署名している公開鍵さえ事前に取得しておけばその公開鍵を使って取得した証明書が通信先が発行したものであることを保証できる。しかも複数の証明書の署名を1つの秘密鍵で行えば検証用に管理する公開鍵の数自体が減らせるということになる。このような証明書自体の署名検証に使う公開鍵をさらに別の証明書に埋め込んでおき、その証明書もまた別の証明書の公開鍵で署名するといったことを繰り返すことにより、無数にある末端の証明書をその証明書の連鎖で繋がれた数個の公開鍵だけ管理していれば検証することが可能になるというわけだ。X.509 はその証明書の連鎖の方式と、その連鎖を実現させるための証明書データなどの形式を規格化したものになる。</p>
<p>X.509 のアーキテクチャには、以下のエンティティが登場する:</p>
<dl class="docutils">
<dt>末端エンティティ</dt>
<dd>PKI により保証された証明書を使用するシステム。</dd>
<dt>認証局 (Certification Authority、略して CA)</dt>
<dd>証明書に署名する第三者機関。</dd>
<dt>登録局 (Registration Authority、略して RA)</dt>
<dd>証明書申請者の本人性を審査・確認する機関。CA が行う場合もあるが、他の機関に委任されることもある。</dd>
<dt>CRL 発行者 (CRL Issuer)</dt>
<dd>証明書失効リスト (Certificate Revocation List、略して CRL) を生成して署名する機関。CA が行う場合もあるが、他の機関に委任されることもある。</dd>
<dt>リポジトリ (Repository)</dt>
<dd>証明書と CRL を管理、配布するシステム。</dd>
</dl>
<p>X.509 ではこれらのエンティティにより、以下のやりとりが行われることによって、PKI の管理を行う:</p>
<dl class="docutils">
<dt>登録</dt>
<dd>CA に認証先を登録するプロセス。これは、RA を介して行われることもある。認証先は、末端エンティティもしくは別の認証局である。</dd>
<dt>証明書発行</dt>
<dd>登録された認証先に対して CA が証明書を発行するプロセス。証明書が発行されるとリポジトリに登録される。</dd>
<dt>証明書更新</dt>
<dd>古くなった証明書の代わりに CA から新しく証明書を発行するプロセス。公開鍵・秘密鍵のペアは定期的に更新されなければならないため、このプロセスは定期的に発生する。</dd>
<dt>証明書失効要求</dt>
<dd>証明書を何らかの理由により有効期限前に失効させるべきであることを CA に通知するプロセス。証明書は有効期限を持ち、通常はその期限の満了まで有効だが、秘密鍵の漏洩など何らかの理由によりその有効期限前に証明書を失効させる必要が生まれる場合がある。その場合に CA に通知し、CA は CRL にその証明書を載せることを CRL 発行者に依頼し、リポジトリの更新とともに CRL を通じて証明書が失効されたことが証明書検証者に通知される。</dd>
</dl>
<p>X.509 はそれぞれのプロセスは規格化せず、それぞれの CA に任せるが、発行する証明書及び CRL の形式と、それらの検証方法を規格化している。まずは証明書の構造から見ていく。X.509 証明書は、</p>
<dl class="docutils">
<dt>署名対象証明書 (To Be Signed Certificate、略して TBS Certificate)</dt>
<dd>証明書本体の情報。証明書の持ち主及び証明書を発行した CA の情報、認証先の公開鍵、有効期限などの情報が含まれている。載せられる情報については後述する。</dd>
<dt>署名アルゴリズム識別子 (Signature Algorithm)</dt>
<dd>署名に使うアルゴリズムの識別子。</dd>
<dt>デジタル署名 (Signature Value)</dt>
<dd>署名対象証明書に対して署名アルゴリズム識別子に示される署名アルゴリズムで生成された CA による署名。これにより、署名対象証明書が改竄されることを防ぎつつ、CA から発行されたものであることが保証できる。</dd>
</dl>
<p>の3つにより構成される。署名対象証明書には、以下の情報が載っている:</p>
<dl class="docutils">
<dt>バージョン</dt>
<dd>X.509 のバージョン。X.509 は v1 から今までバージョン更新が2回あり、最新の v3 が現在最も多く使用されているバージョンである。この記事では、v3 しか扱わないので、基本ここは 3 が埋まってると思って良い。</dd>
<dt>シリアル番号</dt>
<dd>証明書発行者毎に各証明書に振られる一意な正整数による番号。つまり、各証明書は発行者とシリアル番号により一意に定まる。</dd>
<dt>署名アルゴリズム識別子</dt>
<dd>これは証明書発行の際与えられた識別子で、証明書本体の署名に使われたアルゴリズムの識別子と一致している必要がある。</dd>
<dt>発行者 (Issuer)</dt>
<dd>証明書発行元 (認証元) を識別する名前。空でない key-value による列で定義される。標準的には、国 (country)、組織 (organization)、組織単位 (organizational unit)、識別名の修飾子 (distinguished name qualifier)、州または地方の名前 (state or province name)、共通名 (common name) を key とした属性が埋められるようにすることが規定されており、これらの属性が使われていることが多い。</dd>
<dt>有効性 (Validity)</dt>
<dd>証明書の有効期間。証明書が有効化される日時 (not before)、証明書の有効期間が終了する日時 (not after) が設定できる。</dd>
<dt>主体者 (Subject)</dt>
<dd>証明書の公開鍵により保証されるエンティティを識別する名前。発行者名と同じく、空でない key-value による列で定義される。ただ、後述するが昨今は個人情報保護の観点もあって、共通名のみ埋める CA も結構出てきている。一般には、TLS 用の末端エンティティの場合共通名にドメイン名が用いられるのが一般的で、これを前提に HTTPS の意味論が規定されていた時代もあったが、今は代わりに後述する subjectAltName という拡張フィールドで明確にドメイン名を指定するのが一般的で、共通名の検証は HTTPS では禁じられている <a class="footnote-reference" href="#rfc-6125-sec6-4-4" id="auto-id-2">[2]</a>。CA 証明書の場合は、発行する証明書の発行者と同じにする必要がある。</dd>
<dt>主体者公開鍵情報 (Subject Public Key Info)</dt>
<dd>主体者の検証に使う公開鍵と検証用の署名アルゴリズムの識別子。主体者が TLS 用の末端エンティティであれば TLS で使う公開鍵が、CA であれば発行された証明書の署名検証用に使う公開鍵が書かれることになる。</dd>
<dt>拡張 (Extensions)</dt>
<dd>key-value により載せられる任意の拡張で、CA用の独自の情報を埋め込んだりできる。X.509 内で標準的に規定されており、証明書検証に影響を与える拡張もある。</dd>
</dl>
<p>他に一意識別子が載せられるが、これは現在は非推奨で特に要件は設けられておらず、載せても載せなくても良い。他に標準拡張として</p>
<dl class="docutils">
<dt>鍵識別子</dt>
<dd>鍵を識別する識別子。発行者、主体者それぞれに対して付加できる。</dd>
<dt>鍵使用目的 (Key Usage)</dt>
<dd>証明書に含まれる公開鍵の使用目的。複数指定可能。デジタル署名 (digitalSignature)、否認防止 (nonRepudiation)、鍵暗号化 (keyEncipherment)、データ暗号化 (dataEncipherment)、鍵交換 (keyAgreement)、証明書署名 (keyCertSign)、CRL署名 (cRLSign)の中から選ぶ。鍵交換についてはさらにデータ暗号化 (encipherOnly)、データ復号 (decipherOnly)の制御が指定できる。</dd>
<dt>証明書ポリシー (Certificate Policies)</dt>
<dd>証明書及びその証明書による証明書パスに連なる証明書の利用目的を表すデータ。今回は詳しく触れない。</dd>
<dt>ポリシーマッピング (Policy Mappings)</dt>
<dd>CA 証明書において、ポリシー間のマッピングを規定するデータ。今回は詳しく触れない。</dd>
<dt>主体者別名 (Subject Alternative Name)</dt>
<dd>主体者の別名。複数指定可能。複数の末端エンティティについて、一つの証明書を使いたい時に用いられる。TLS 用証明書では慣例的に、主体者名に証明書識別のための共通名を設定し、主体者別名でドメイン名 (DNS 名) を指定するのが一般的。</dd>
<dt>基本制約 (Basic Constraints)</dt>
<dd>主体者が CA であるか、及びこの証明書が含まれる証明書パス中の中間証明書の最大の数 (最大長) を規定。拡張と言いながらこの拡張は必ず含める必要がある。つまり、X.509 では、CA 証明書かどうかを必ず規定する必要があるため、証明書署名用の証明書を、末端エンティティ用に使うことはできない。証明書パスの最大長は、CA 証明書である場合のみ指定できる。</dd>
<dt>ポリシー制約 (Policy Constraints)</dt>
<dd>CA 証明書の場合に、受け入れ可能なポリシーを規定する。今回は詳しく触れない。</dd>
<dt>拡張鍵使用目的 (Extended Key Usage)</dt>
<dd>鍵使用目的に加えて追加で指定できる公開鍵の使用目的。サーバ認証 (serverAuth)、クライアント認証 (clientAuth)、コード署名 (codeSigning)、メール保護 (emailProtection)、電子タイムスタンプ (timeStamping)、OCSP署名 (OCSPSigning)が指定できる。また特別に、任意の目的に利用可能 (anyExtendedKeyUsage) であることが指定できる。</dd>
<dt>CRL 配布点 (CRL Distribution Points)</dt>
<dd>CRL の取得方法を規定する。複数指定可能。いくつか項目が指定できるが、基本的には CRL がダウンロードできる URI だけが指定されていることが多い。</dd>
<dt>任意ポリシー禁止 (Inhibit anyPolicy)</dt>
<dd>証明書ポリシーで anyPolicy の使用を禁じることを規定する。今回は詳しく触れない。</dd>
<dt>機関情報アクセス (Authority Information Access)</dt>
<dd>証明書の発行者に関するサービスへのアクセス方法。CA 証明書の配布 URL や、OCSP レスポンダの URL などが書いてある場合が多い。</dd>
</dl>
<p>他にもいくつか標準拡張はあるが、主なものはこんな感じ。これらの情報を元に、X.509 では証明書パスが与えられた時に以下を検証する:</p>
<ul class="simple">
<li><dl class="first docutils">
<dt>証明書パスの出だしはトラストアンカーに載っている、つまり既に知っている証明書である。</dt>
<dd><ul class="first last">
<li>一般にこの出だしの証明書をルート証明書といい、その証明書の発行元 CA をルート CA という。ブラウザや OS には信頼するルート CA の証明書のデータベースがインストールされており、これが X.509 におけるトラストアンカーとなっている。</li>
<li>ルート CA は発行者が自分自身になっている自己署名になっている場合が多い。このような他の認証局の認証によらずトラストアンカーによる認証を受ける必要がある CA を、自己認証 CA と呼んだりもする。</li>
</ul>
</dd>
</dl>
</li>
<li>証明書パスに載っている証明書は、出だしを除いて、その証明書の発行者名と一つ手前の証明書の主体者名が一致しており、一つ手前の証明書の主体者公開鍵で署名が検証できる。</li>
<li>証明書パスに載っている証明書は、検証時刻においてCRL に載っておらず全て有効期間内である。</li>
<li>証明書パスに載っている証明書は、拡張で規定される制約を満たす。</li>
</ul>
<p>これにより、TLS においてルート CA までの証明書パスをサーバから取得すれば、ルート CA 証明書を持っているだけで、X.509 PKI と主体者名による判定により公開鍵が主体者のものであることが保証できるというわけだ。</p>
<p>HTTPS サイトの X.509 証明書を見るビュワーは、大体どのブラウザにも搭載されてるので、結構手軽にみることができる。OpenSSL コマンドで見ることも可能だ。例えば、我らが github.com の証明書は以下のように見ることができる:</p>
<pre class="literal-block">
$ openssl s_client -connect github.com:443 -showcerts
CONNECTED(00000005)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert TLS Hybrid ECC SHA384 2020 CA1
verify return:1
depth=0 C = US, ST = California, L = San Francisco, O = "GitHub, Inc.", CN = github.com
verify return:1
write W BLOCK
---
Certificate chain
0 s:/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=github.com
i:/C=US/O=DigiCert Inc/CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1
-----BEGIN CERTIFICATE-----
MIIFajCCBPGgAwIBAgIQDNCovsYyz+ZF7KCpsIT7HDAKBggqhkjOPQQDAzBWMQsw
CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTAwLgYDVQQDEydEaWdp
Q2VydCBUTFMgSHlicmlkIEVDQyBTSEEzODQgMjAyMCBDQTEwHhcNMjMwMjE0MDAw
MDAwWhcNMjQwMzE0MjM1OTU5WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs
aWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHVi
LCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D
AQcDQgAEo6QDRgPfRlFWy8k5qyLN52xZlnqToPu5QByQMog2xgl2nFD1Vfd2Xmgg
nO4i7YMMFTAQQUReMqyQodWq8uVDs6OCA48wggOLMB8GA1UdIwQYMBaAFAq8CCkX
jKU5bXoOzjPHLrPt+8N6MB0GA1UdDgQWBBTHByd4hfKdM8lMXlZ9XNaOcmfr3jAl
BgNVHREEHjAcggpnaXRodWIuY29tgg53d3cuZ2l0aHViLmNvbTAOBgNVHQ8BAf8E
BAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIGbBgNVHR8EgZMw
gZAwRqBEoEKGQGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRMU0h5
YnJpZEVDQ1NIQTM4NDIwMjBDQTEtMS5jcmwwRqBEoEKGQGh0dHA6Ly9jcmw0LmRp
Z2ljZXJ0LmNvbS9EaWdpQ2VydFRMU0h5YnJpZEVDQ1NIQTM4NDIwMjBDQTEtMS5j
cmwwPgYDVR0gBDcwNTAzBgZngQwBAgIwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3
dy5kaWdpY2VydC5jb20vQ1BTMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGG
GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2Nh
Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExTSHlicmlkRUNDU0hBMzg0MjAy
MENBMS0xLmNydDAJBgNVHRMEAjAAMIIBgAYKKwYBBAHWeQIEAgSCAXAEggFsAWoA
dwDuzdBk1dsazsVct520zROiModGfLzs3sNRSFlGcR+1mwAAAYZQ3Rv6AAAEAwBI
MEYCIQDkFq7T4iy6gp+pefJLxpRS7U3gh8xQymmxtI8FdzqU6wIhALWfw/nLD63Q
YPIwG3EFchINvWUfB6mcU0t2lRIEpr8uAHYASLDja9qmRzQP5WoC+p0w6xxSActW
3SyB2bu/qznYhHMAAAGGUN0cKwAABAMARzBFAiAePGAyfiBR9dbhr31N9ZfESC5G
V2uGBTcyTyUENrH3twIhAPwJfsB8A4MmNr2nW+sdE1n2YiCObW+3DTHr2/UR7lvU
AHcAO1N3dT4tuYBOizBbBv5AO2fYT8P0x70ADS1yb+H61BcAAAGGUN0cOgAABAMA
SDBGAiEAzOBr9OZ0+6OSZyFTiywN64PysN0FLeLRyL5jmEsYrDYCIQDu0jtgWiMI
KU6CM0dKcqUWLkaFE23c2iWAhYAHqrFRRzAKBggqhkjOPQQDAwNnADBkAjAE3A3U
3jSZCpwfqOHBdlxi9ASgKTU+wg0qw3FqtfQ31OwLYFdxh0MlNk/HwkjRSWgCMFbQ
vMkXEPvNvv4t30K6xtpG26qmZ+6OiISBIIXMljWnsiYR1gyZnTzIg3AQSw4Vmw==
-----END CERTIFICATE-----
1 s:/C=US/O=DigiCert Inc/CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
Server certificate
subject=/C=US/ST=California/L=San Francisco/O=GitHub, Inc./CN=github.com
issuer=/C=US/O=DigiCert Inc/CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 2801 bytes and written 351 bytes
---
New, TLSv1/SSLv3, Cipher is AEAD-CHACHA20-POLY1305-SHA256
...
---
read R BLOCK
read R BLOCK
^D
</pre>
<p>この場合の証明書パスは</p>
<pre class="literal-block">
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert TLS Hybrid ECC SHA384 2020 CA1
verify return:1
depth=0 C = US, ST = California, L = San Francisco, O = "GitHub, Inc.", CN = github.com
verify return:1
</pre>
<p>になっており、それぞれの depth に続く key-value が主体者名を表す。ルート CA が DigiCert のもので、そこから DigiCert TLS CA 用の証明書が発行され、さらに DigiCert TLS CA から github.com の末端エンティティ証明書が発行されている。ルート CA と末端エンティティの間の証明書を持つ CA を中間 CA と呼んだりする。今回は中間 CA 一つの証明書が 3 つ連なる証明書パスとなっている。 <tt class="docutils literal"><span class="pre">-----BEGIN</span> <span class="pre">CERTIFICATE-----</span></tt>、 <tt class="docutils literal"><span class="pre">-----END</span> <span class="pre">CERTIFICATE-----</span></tt> で囲まれたデータが証明書データになる。証明書データは、ASN.1 という表現により規定されてるのだが、その符号化方式は幾つかある。一般的にはバイナリ表現として DER、表示用の表現として DER を Base64 エンコードする符号化形式 PEM が一般に用いられている。TLS では DER でやりとりが行われ、OpenSSL コマンドはそれを PEM 形式で表示しているというわけだ。この符号化されたデータの中身を見たい場合は、証明書データを以下の要領で OpenSSL に食わしてやれば良い:</p>
<pre class="literal-block">
$ cat github.com.pem
-----BEGIN CERTIFICATE-----
MIIFajCCBPGgAwIBAgIQDNCovsYyz+ZF7KCpsIT7HDAKBggqhkjOPQQDAzBWMQsw
...
-----END CERTIFICATE-----
$ openssl x509 -in github.com.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
0c:d0:a8:be:c6:32:cf:e6:45:ec:a0:a9:b0:84:fb:1c
Signature Algorithm: ecdsa-with-SHA384
Issuer: C=US, O=DigiCert Inc, CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1
Validity
Not Before: Feb 14 00:00:00 2023 GMT
Not After : Mar 14 23:59:59 2024 GMT
Subject: C=US, ST=California, L=San Francisco, O=GitHub, Inc., CN=github.com
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:a3:a4:03:46:03:df:46:51:56:cb:c9:39:ab:22:
cd:e7:6c:59:96:7a:93:a0:fb:b9:40:1c:90:32:88:
36:c6:09:76:9c:50:f5:55:f7:76:5e:68:20:9c:ee:
22:ed:83:0c:15:30:10:41:44:5e:32:ac:90:a1:d5:
aa:f2:e5:43:b3
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:0A:BC:08:29:17:8C:A5:39:6D:7A:0E:CE:33:C7:2E:B3:ED:FB:C3:7A
X509v3 Subject Key Identifier:
C7:07:27:78:85:F2:9D:33:C9:4C:5E:56:7D:5C:D6:8E:72:67:EB:DE
X509v3 Subject Alternative Name:
DNS:github.com, DNS:www.github.com
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl3.digicert.com/DigiCertTLSHybridECCSHA3842020CA1-1.crl
Full Name:
URI:http://crl4.digicert.com/DigiCertTLSHybridECCSHA3842020CA1-1.crl
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.2
CPS: http://www.digicert.com/CPS
Authority Information Access:
OCSP - URI:http://ocsp.digicert.com
CA Issuers - URI:http://cacerts.digicert.com/DigiCertTLSHybridECCSHA3842020CA1-1.crt
X509v3 Basic Constraints:
CA:FALSE
1.3.6.1.4.1.11129.2.4.2:
......-....c.K..6.!...;`Z#.)N.3GJr...F..m..%......QG..P..+.....G0E. .<`2~ Q....}M...H.FWk..72O%.6....!...~.|..&6..[...Y.b .mo..
Signature Algorithm: ecdsa-with-SHA384
30:64:02:30:04:dc:0d:d4:de:34:99:0a:9c:1f:a8:e1:c1:76:
5c:62:f4:04:a0:29:35:3e:c2:0d:2a:c3:71:6a:b5:f4:37:d4:
ec:0b:60:57:71:87:43:25:36:4f:c7:c2:48:d1:49:68:02:30:
56:d0:bc:c9:17:10:fb:cd:be:fe:2d:df:42:ba:c6:da:46:db:
aa:a6:67:ee:8e:88:84:81:20:85:cc:96:35:a7:b2:26:11:d6:
0c:99:9d:3c:c8:83:70:10:4b:0e:15:9b
</pre>
</div>
<div class="section" id="acme">
<h2>ACME による証明書発行<a class="headerlink" href="#acme" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、X.509 PKI により、認証局の運営とそこから発行された証明書の管理がちゃんとできれば、技術的に TLS 通信の前提となる PKI の機能を実現できることは分かった。ただ問題は、認証局の運営をどうするかである。ここら辺は長年そこまで厳密な規格はなされておらず、各 CA がブラウザなどの要望を踏みながら各自が手続きを整備している。一般的なフローは、</p>
<ol class="arabic simple">
<li>証明書に載せる公開鍵、主体者名などの情報が書かれた証明書署名要求 (Certificate Signing Request、略して CSR) を作成</li>
<li>CA に CSR と本人確認情報などを渡す</li>
<li>CA (RA に委任している場合は RA) はドメインの所有者であることや本人確認情報などの審査を行う</li>
<li>審査が通ったら CSR を元に証明書を発行</li>
</ol>
<p>という感じだ。審査内容は、CA によってまちまちだが、主要な CA・ブラウザにより構成された CA/Browser Forum である程度の基準値が設けられており <a class="footnote-reference" href="#cabforum-servercert" id="auto-id-3">[3]</a>、以下の区分がある:</p>
<dl class="docutils">
<dt>ドメイン認証 (Domain Validated)</dt>
<dd>エンティティのドメインを、証明書署名要求者が所有していることが確認された証明書。そのドメインにメールを送る、トークンを TXT レコードで設定するなど確認方法はいくつかある。</dd>
<dt>実在組織認証 (Organization Validated)</dt>
<dd>主体者名に指定された組織が実在し、そのエンティティを所有していることが確認された証明書。</dd>
<dt>実在個人認証 (Individual Validated)</dt>
<dd>主体者名に指定された個人が実在し、そのエンティティを所有していることが確認された証明書。</dd>
<dt>拡張認証 (Extended Validated)</dt>
<dd>CA/Browser Forum の最初の仕事で、標準化された法的な実在性確認などを含む認証プロセスを通して主体者が確認された証明書。</dd>
</dl>
<p>ここら辺は色々歴史的な紆余曲折があり、ドメイン認証は PKI としての機能には沿ったもので運用コストも安い反面ドメインを持っていれば誰でも取れるためフィッシングの温床になり、それを問題視して拡張認証が生まれたが、世の中の人はサイトの所有者情報をそこまでちゃんと見ていないことが分かって実はフィッシング対策にそれほどならなかったなど、まあ色々ある。最近の潮流としては、主体者情報に組織、個人の情報を含める場合はちゃんと実在認証をやる、PKI 技術にただ乗っかりたい場合は主体者情報はその証明書を使用するエンティティを識別できる情報を共通名に入れるだけにしておいて、ドメイン認証は最低限やるが、実在確認までは必要ないといった感じに落ち着いてきたように思う。さて、その潮流において、ドメイン認証だけであれば別に大層なことをやる必要はなく、手続きをサーバ間のやり取りのみで自動化できる。そのような中で生まれたのが Let's Encrypt というサービスである。Let's Encrypt はドメイン認証証明書の発行手続きを完全自動化することで、CA 業務コストをサーバ管理のみにし、TLS を無償で使用できるようにすることを目指したサービスである。そして、このサービス提供の中で生み出され規格化された証明書自動管理プロトコルが Automatic Certificate Management Environment、略して ACME になる。</p>
<p>ACME は HTTPS 上でサーバ-クライアントが JSON POST で話す割と今時のプロトコルで、</p>
<dl class="docutils">
<dt>アカウント作成</dt>
<dd>サービス規約に同意し、CA のサービスを受け取る、クライアントのユーザ単位リソースを作成する。</dd>
<dt>証明書の注文</dt>
<dd>証明書が必要なことを CA に伝え、発行手続きを開始する。</dd>
<dt>識別子の承認</dt>
<dd>CA から証明書発行に必要な認証手続きを受ける。</dd>
<dt>証明書の発行</dt>
<dd>注文して認証された証明書を取得する。</dd>
<dt>証明書の失効</dt>
<dd>証明書を有効期間前に失効させたい旨を CA に伝える。</dd>
</dl>
<p>の機能をサポートしている。初めて証明書を発行するまでの流れは以下のようになる:</p>
<ol class="arabic simple">
<li><dl class="first docutils">
<dt>アカウント作成</dt>
<dd><ul class="first last">
<li>このステップでは、証明書を管理するためのサービスユーザ単位を発行する。</li>
<li>クライアントは、認証兼リクエスト署名検証用の公開鍵、サービス規約への同意の意思と、連絡先などの情報をサーバに渡すと、サーバからアカウントIDが発行される。</li>
<li>クライアントは発行されたアカウント ID と秘密鍵を保存しておき、この後の手順では ID と秘密鍵から生成された署名をリクエストに含めるようにする。</li>
</ul>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>証明書の注文</dt>
<dd><ul class="first last">
<li>このステップでは、要求される証明書の識別子の認証と証明書発行の手続きに入る。</li>
<li>クライアントは発行したい証明書の主体者識別子をサーバに送り、サーバは認証手続きを開始し、クライアントに認証状態を取得できる URL と証明書発行手続きに進む URL を返す。</li>
<li>識別子の認証は単体で事前に行うこともできる。</li>
<li>識別子自体は、現在はドメイン名のみ対応している。これについては詳しくは後述する。</li>
</ul>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>識別子の承認</dt>
<dd><ul class="first last">
<li>このステップでは、識別子が指し示すエンティティがクライアントから制御できること、つまりアカウントに所有されていることを確認する。</li>
<li>クライアントは、認証状態を確認する URL から課題を取得し、課題への対応の準備ができたらサーバに通知する。サーバは課題への対応を確認し、識別子の承認を行う。クライアントは承認が行われるまで認証状態をポーリングしながら待つ。</li>
<li>課題の方式は現在 HTTP 検証、DNS 検証の2つがある。これについては後述する。</li>
</ul>
</dd>
</dl>
</li>
<li><dl class="first docutils">
<dt>証明書の発行</dt>
<dd><ul class="first last">
<li>このステップでは、承認済みの識別子に対して証明書を発行する。</li>
<li>クライアントは、証明書発行手続き用の URL から CSR をサーバに送り、サーバはその識別子が承認済みであること、CSR の内容が許容可能であることを確認し、証明書ダウンロード用 URL を返す。</li>
</ul>
</dd>
</dl>
</li>
</ol>
<p>証明書の更新時はアカウント作成を除くステップを繰り返す。これにより、クライアント-サーバ間の HTTPS でのやり取りのみで CA から証明書を受け取ることができる。</p>
<p>さて、後回しにした識別子の認証だが、ACME では現状認証方式としてドメイン認証のみ対応している。ただ、プロトコル自体は組織認証、拡張認証などにも対応できるよう設計されており、将来的にはそれらのサポートもされるかもしれない。ドメイン認証は、HTTP による検証と DNS による検証の2通りに対応している。HTTP 検証では、課題として受け取ったトークンとアカウントに紐づく鍵のフィンガープリントを <tt class="docutils literal"><span class="pre">http://<domain>/.well-known/acme-challenge/<token></span></tt> にデプロイできることにより、そのドメインがアカウントに所有されているとみなす。DNS 検証では、 <tt class="docutils literal"><span class="pre">_acme-challenge</span></tt> サブドメイン、つまり <tt class="docutils literal"><span class="pre">_acme-challenge.<domain></span></tt> の TXT レコードに、トークンとアカウントに紐づく鍵のフィンガープリントをデプロイできることにより、そのドメインがアカウントに所有されているとみなす。この部分のデプロイをクライアントが自動化できれば、検証も自動化することができる。</p>
</div>
<div class="section" id="caddy-ca">
<h2>Caddy で CA を立てる<a class="headerlink" href="#caddy-ca" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、ここまでで X.509 PKI における CA の役割、ACME による CA と末端エンティティとのやり取りの自動化について見てきた。では、実際に世の中でどう運用されているかだが、まず ACME クライアントの有名どころが <a class="reference external" href="https://github.com/certbot/certbot">Certbot</a> で、ACME サーバとのやり取りと CSR の生成はもちろん、HTTP 検証に必要な項目を Web サーバにデプロイするところまでこなしてくれたり、有効期限によって証明書の再発行を制御する機構なども入っており、結構便利。Let's Encrypt 利用時はお馴染みという感じだろう。Certbot は接続先の ACME サーバとして Let's Encrypt をデフォルトで使うが、接続先をカスタマイズすることもできる。なので手元で ACME サーバを立てて、証明書を ACME 経由で作ることもできる。ACME 対応の CA は Let's Encrypt が自身が使っている <a class="reference external" href="https://github.com/letsencrypt/boulder">Boulder</a> という CA の実装を公開している。他にも <a class="reference external" href="https://smallstep.com/docs/step-ca/#introduction-to-step-ca">smallstep CA</a> というミニマルな実装がある。CA としての機能は欠けてるものも多いが最低限のものは揃ってる。今回紹介する <a class="reference external" href="https://caddyserver.com/">Caddy</a> はバックエンドで <a class="reference external" href="https://smallstep.com/docs/step-ca/#introduction-to-step-ca">smallstep CA</a> を使っている。</p>
<p>さて、今回紹介する Private CA は、Certbot をクライアントに使って、ACME サーバは <a class="reference external" href="https://caddyserver.com/">Caddy</a> という Web サーバで立てる方法だ。 <a class="reference external" href="https://caddyserver.com/">Caddy</a> を使う場合、OCSP レスポンダは諦める必要があるが、まあかなり小規模な常時 TLS 環境を手元で作りたいとかなら、割と手軽でそこまで困らないかなという感じ。 <a class="reference external" href="https://caddyserver.com/">Caddy</a> は割と面白い機能を持った Web サーバで、ACME クライアントの機能を備えて自動で証明書を取得したり更新してくれたり、Private CA を立ててそこから証明書を自動で発行して使ったりしてくれる。さらに、Private CA に対して ACME サーバを立てる機能も持っている。今回はこの機能を使っていく。</p>
<p>caddy のインストールは、<a class="reference external" href="https://caddyserver.com/docs/install">https://caddyserver.com/docs/install</a> に書いてある手順でできる。Debian なら、</p>
<pre class="literal-block">
$ sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
$ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
$ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
$ sudo apt update
$ sudo apt install caddy
</pre>
<p>の手順でリポジトリ追加してパッケージインストール可能。結構お手軽。Docker image もである: <a class="reference external" href="https://hub.docker.com/_/caddy">https://hub.docker.com/_/caddy</a></p>
<p>設定ファイルは <tt class="docutils literal">/etc/caddy/Caddyfile</tt> にある。ドキュメントは <a class="reference external" href="https://caddyserver.com/docs/caddyfile">https://caddyserver.com/docs/caddyfile</a>。入れておくといい設定は、以下:</p>
<pre class="literal-block">
{
auto_https disable_redirects
skip_install_trust
}
</pre>
<p>1つ目は勝手に HTTP サーバが立つのを無効化する設定。Caddy はデフォルトで全てのサイトを HTTPS でサービングし、HTTP には HTTPS へのリダイレクトサーバを立てる。ドメインを指定する場合 Let's Encrypt から証明書を発行、IP アドレスを指定する場合自己署名証明書を発行する。ただ、勝手に 80 ポート占有されるのは微妙なので、リダイレクトの方は無効化しておく。2つ目は、Private CA のルート証明書を Java のトラストアンカーや ca-certificates に加えてくるおせっかい機能を止める。</p>
<p>Private CA の設定は、pki オプションで指定できる:</p>
<pre class="literal-block">
{
pki {
ca local {
root_cn "My Local CA - 2023 ECC Root"
intermediate_lifetime 30d
root {
cert /etc/pki/caddy/ca/local/root.crt
key /etc/pki/caddy/ca/local/root.key
}
}
}
}
</pre>
<p><tt class="docutils literal">root_cn</tt> オプションはルート証明書の共通名を指定する。 <tt class="docutils literal">intermediate_lifetime</tt> は中間証明書の有効期間を 30 日に伸ばす。デフォルトは 7 日。ま、基本デフォルトの期間から変えなくていいと思う。root.cert / root.key はルート証明書とその秘密鍵のファイルを指定している。指定しない場合は自動生成してくれる。証明書の生成は、以下の要領でできる:</p>
<pre class="literal-block">
$ cat > cacert.cnf
[ req ]
distinguished_name = req_distinguished_name
req_extensions = req_ext
default_md = sha512
[ req_distinguished_name ]
commonName = Common Name
commonName_default = My Local CA - 2023 ECC Root
[ req_ext ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always, issuer:always
basicConstraints = critical, CA:TRUE, pathlen:1
keyUsage = critical, cRLSign, keyCertSign
$ openssl req -config cacert.cnf \
-x509 \
-newkey EC \
-pkeyopt ec_paramgen_curve:secp384r1 \
-pkeyopt ec_param_enc:named_curve \
-days 3600 \
-out /etc/pki/caddy/ca/local/root.crt \
-passout 'pass:'
-keyout /etc/pki/caddy/ca/local/root.key
</pre>
<p>これによりルート証明書を永続化しつつ、他のサーバに配布してトラストアンカーに入れておけば、Private CA から発行された証明書で HTTPS サーバを立てて通信できる。Caddy で ACME サーバを立てるには、以下の設定を <tt class="docutils literal">Caddyfile</tt> に追加する:</p>
<pre class="literal-block">
acme.mylocal.domain:6100 {
tls internal
acme_server {
ca local
lifetime 10d
}
}
</pre>
<p>これにより、6100 ポートからの acme.mylocal.domain ホストへのリクエストは ACME サーバで受けるようにできる。 <tt class="docutils literal">tls internal</tt> は Private CA から発行された証明書を使う設定になる。この ACME サーバは Private CA から10日有効の証明書を発行する。デフォルトは 12 時間。流石に 12 時間は短いと思うが、基本 2 日以内にはしとく方がいいだろう。</p>
<p>この ACME サーバから nginx 向けに Certbot を使って証明書を発行してみる。まず、Certbot と Nginx をインストールする。Debian なら、</p>
<pre class="literal-block">
apt install -y nginx certbot
</pre>
<p>で入る。まず、Nginx の方で、Certbot の Web ルートをサービングする HTTP サーバを立てる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">server</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="mi">80</span><span class="p">;</span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="s">[::]:80</span><span class="p">;</span>
<span class="w"> </span><span class="kn">server_name</span><span class="w"> </span><span class="s">_</span><span class="p">;</span>
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/.well-known/acme-challenge/</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">allow</span><span class="w"> </span><span class="s">all</span><span class="p">;</span>
<span class="w"> </span><span class="kn">root</span><span class="w"> </span><span class="s">/var/www/certbot/</span><span class="p">;</span>
<span class="w"> </span><span class="kn">default_type</span><span class="w"> </span><span class="s">"text/plain"</span><span class="p">;</span>
<span class="w"> </span><span class="kn">try_files</span><span class="w"> </span><span class="nv">$uri</span><span class="w"> </span><span class="p">=</span><span class="mi">404</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">return</span><span class="w"> </span><span class="mi">301</span><span class="w"> </span><span class="s">https://</span><span class="nv">$host$request_uri</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>次に certbot で証明書を発行する:</p>
<pre class="literal-block">
env REQUESTS_CA_BUNDLE=/etc/pki/caddy/ca/local/root.crt \
certbot certonly
--server https://acme.mylocal.domain:6100/acme/local/directory
--webroot --webroot-path /var/www/certbot
--domain www.mylocal.domain
--email contact@myemail.domain
--agree-tos
--no-eff-email
</pre>
<p><tt class="docutils literal">REQUESTS_CA_BUNDLE</tt> は Python の環境変数で、トラストアンカーとなるルート証明書のバンドルファイルのパスを指定できる。今回は Private CA のルート証明書を指定している。 <tt class="docutils literal"><span class="pre">--server</span></tt> には、ACME サーバのディレクトリパスを指定する。デフォルトは、Let's Encrypt の <a class="reference external" href="https://acme-v02.api.letsencrypt.org/directory">https://acme-v02.api.letsencrypt.org/directory</a> が使われているが、今回は Caddy の ACME サーバの URL を使っている。Caddy の場合、ルートパスは、 <tt class="docutils literal"><span class="pre">/acme/<CA</span> <span class="pre">name>/directory</span></tt> になる。webroot はトークンファイルをデプロイして HTTP サーバにそれをサーブしてもらい、HTTP 検証で課題をこなすモードで、 <tt class="docutils literal">/var/www/cerbot</tt> にトークンファイルが置かれるのでそれを Nginx が ACME サーバに返すことで識別子の承認を得る。 <tt class="docutils literal"><span class="pre">agree-tos</span></tt> はサービス利用規約に同意するフラグで、 <tt class="docutils literal"><span class="pre">--no-eff-mail</span></tt> は指定したメールアドレスで電子フロンティア財団からのニュースを購読しないフラグ。これで、ドメイン設定などをちゃんとしていれば、 <tt class="docutils literal">/etc/letsencrypt/live/www.mylocal.domain</tt> に証明書と秘密鍵などが発行される。</p>
<p>後は、nginx 側で HTTPS サーバに証明書を設定すればよい:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">server</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="mi">443</span><span class="w"> </span><span class="s">ssl</span><span class="w"> </span><span class="s">http2</span><span class="p">;</span>
<span class="w"> </span><span class="kn">listen</span><span class="w"> </span><span class="s">[::]:443</span><span class="w"> </span><span class="s">ssl</span><span class="w"> </span><span class="s">http2</span><span class="p">;</span>
<span class="w"> </span><span class="kn">server_name</span><span class="w"> </span><span class="s">www.mylocal.domain</span><span class="p">;</span>
<span class="w"> </span><span class="kn">ssl_certificate</span><span class="w"> </span><span class="s">/etc/letsencrypt/live/www.mylocal.domain/fullchain.pem</span><span class="p">;</span>
<span class="w"> </span><span class="kn">ssl_certificate_key</span><span class="w"> </span><span class="s">/etc/letsencrypt/live/www.mylocal.domain/privkey.pem</span><span class="p">;</span>
<span class="w"> </span><span class="kn">ssl_trusted_certificate</span><span class="w"> </span><span class="s">/etc/letsencrypt/live/www.mylocal.domain/chain.pem</span><span class="p">;</span>
<span class="w"> </span><span class="kn">add_header</span><span class="w"> </span><span class="s">Strict-Transport-Security</span><span class="w"> </span><span class="s">"max-age=63072000</span><span class="p">;</span><span class="w"> </span><span class="kn">includeSubDomains"</span><span class="w"> </span><span class="s">always</span><span class="p">;</span>
<span class="w"> </span><span class="kn">add_header</span><span class="w"> </span><span class="s">X-Frame-Options</span><span class="w"> </span><span class="s">"SAMEORIGIN"</span><span class="w"> </span><span class="s">always</span><span class="p">;</span>
<span class="w"> </span><span class="kn">add_header</span><span class="w"> </span><span class="s">X-Content-Type-Options</span><span class="w"> </span><span class="s">"nosniff"</span><span class="w"> </span><span class="s">always</span><span class="p">;</span>
<span class="w"> </span><span class="kn">add_header</span><span class="w"> </span><span class="s">X-XSS-Protection</span><span class="w"> </span><span class="s">"1</span><span class="p">;</span><span class="w"> </span><span class="kn">mode=block"</span><span class="w"> </span><span class="s">always</span><span class="p">;</span>
<span class="w"> </span><span class="kn">location</span><span class="w"> </span><span class="s">/</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kn">return</span><span class="w"> </span><span class="mi">200</span><span class="w"> </span><span class="s">"OK"</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>証明書は定期的に更新する必要がある。特に ACME では、自動で管理できる分発行される証明書の有効期間が短くしてあることが多い。Private CA なら尚更、管理をルーズにする分有効期間は短くしておく方がいいだろう。さて、有効期間を短くする場合、手動での更新とかやってられないので、証明書更新の自動化が必要になってくるだろう。Debian の Certbot パッケージはデフォルトで weekly で全部の証明書更新をかける timer を入れてくれる。ただ、今回は weekly じゃ追いつかないのとルート証明書の指定が必要なので、自分で timer を書くのが良いだろう。まず、systemd oneshot service を以下の感じで書く:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">[Unit]</span>
<span class="na">Description</span><span class="o">=</span><span class="s">certbot renew service for www.mylocal.domain</span>
<span class="k">[Service]</span>
<span class="na">Type</span><span class="o">=</span><span class="s">oneshot</span>
<span class="na">Environment</span><span class="o">=</span><span class="s">REQUESTS_CA_BUNDLE=/etc/pki/caddy/ca/local/root.crt</span>
<span class="na">ExecStart</span><span class="o">=</span><span class="s">certbot renew </span>\
<span class="w"> </span><span class="s">--cert-name www.mylocal.domain </span>\
<span class="w"> </span><span class="s">--post-hook 'systemctl reload nginx'</span>
</pre></div></td></tr></table></div>
<p>これを <tt class="docutils literal">/etc/systemd/system/certbot_renew_www.mylocal.domain.service</tt> におく。後はこの service を呼び出す systemd timer を以下の感じで書く:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">[Unit]</span>
<span class="na">Description</span><span class="o">=</span><span class="s">certbot renew timer for www.mylocal.domain</span>
<span class="na">ConditionPathExists</span><span class="o">=</span><span class="s">/etc/letsencrypt/live/www.mylocal.domain/fullchain.pem</span>
<span class="k">[Timer]</span>
<span class="na">OnCalendar</span><span class="o">=</span><span class="s">daily</span>
<span class="na">Persistent</span><span class="o">=</span><span class="s">true</span>
<span class="k">[Install]</span>
<span class="na">WantedBy</span><span class="o">=</span><span class="s">timers.target</span>
</pre></div></td></tr></table></div>
<p>これを <tt class="docutils literal">/etc/systemd/system/certbot_renew_www.mylocal.domain.timer</tt> におく。後は、 <tt class="docutils literal">systemctl start certbot_renew_www.mylocal.domain.timer</tt> で timer を開始しておけば、daily で更新が走るようになる。後はルート証明書をブラウザにインストールするなりしておけば良い。</p>
<p>これで、プライベートネットワーク内、プライベートアドレスについても手軽に証明書発行して TLS 対応できる。CRL 配布対応がないのが残念だが、小規模なオレオレ環境なら特に困らないだろう。</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今回は X.509 PKI の仕組みとその管理を自動化する ACME プロトコルについて紹介した。また、Caddy という Web サーバで、Private CA の ACME サーバを立て、証明書を自動発行し、プライベートネットワーク内で TLS 環境を構築する方法を紹介した。これによりプライベートネットワーク内であっても TLS 網が結構手軽に構築できるし、Let's Encrypt の検証環境を手元で構築したりもできる。</p>
<p>TLS プロトコル自体の説明は巷に結構あるのだが、X.509 PKI の情報となるとかなり限られるし、毎回調べることになってたので書いた。X.509 の拡張とかなんとなく指定してるものも多かったので、割と情報整理になってよかった。後、ACME もなんとなくの部分が多かったので、知識補強になったかなという感じ。ACME もうちょっと流行ってほしい。2020 年過ぎても証明書の手動更新してるのは流石になあって感じがある。まあ、TLS 必須と謳われてる割には CA/B は迷走してる感じもあるが。</p>
<p>では、今回はこれで。</p>
<table class="docutils footnote" frame="void" id="rfc-5280" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td><a class="reference external" href="https://datatracker.ietf.org/doc/html/rfc5280">https://datatracker.ietf.org/doc/html/rfc5280</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="rfc-6125-sec6-4-4" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td><a class="reference external" href="https://datatracker.ietf.org/doc/html/rfc6125#section-6.4.4">https://datatracker.ietf.org/doc/html/rfc6125#section-6.4.4</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="cabforum-servercert" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[3]</a></td><td><a class="reference external" href="https://github.com/cabforum/servercert">https://github.com/cabforum/servercert</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/05/operating-private-ca-with-acme.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/05/operating-private-ca-with-acme.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Mastodon へのシェアボタンを追加した2023-03-08T12:54:34+09:002023-03-08T12:54:34+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-03-08:/blog/posts/2023/03/mastodon-share-button/<p>Mastodon への記事共有を行うボタンを追加したので、その仕組みについてちょっと解説しとこうかなと思う。是非、利用して …</p><p>Mastodon への記事共有を行うボタンを追加したので、その仕組みについてちょっと解説しとこうかなと思う。是非、利用してみてくれ。一番最後にあるぞ。</p>
<div class="section" id="auto-id-1">
<h2>先行研究<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Mastodon に移ってきてから、記事投稿機能は追加したかったのだが、そもそも分散的な Mastodon の世界において、共有先とはみたいな感じになってあまりとっかかりが見いだせなかった。そんな中で、 <a class="reference external" href="https://blog.3qe.us/entry/2023/01/26/220631">マストドンのシェアボタンを自作した(追記あり)(今日から使えます) - Lambdaカクテル</a> と言う記事を見つけた。この記事は、色々先行研究がまとまっていて、その上で改良版が提供されており、めちゃくちゃお世話になった。圧倒的感謝という感じ。ただ、モノは動かなかったので、自分で作ろうと相なった。</p>
<p>まず、僕が共有ボタンに求める要件は以下のようなことだった:</p>
<dl class="docutils">
<dt>日本語対応している</dt>
<dd>Mastodon の場合基本共有ボタンのためにワンステップ必要になってくる。つまり、分散的だからこそ、どこに共有すればいいか分からないので、共有先を選択する中継点が必要になる。このブログの読者は基本日本語読者なので (というか、記事は日本語で書かれているので)、この中継点は日本語に対応しておいてほしい。</dd>
<dt>読者が信用しているサービスの他に、共有のために不透明なサービスを通したくない</dt>
<dd>読者にとって、記事共有なんてそれほど大した動機でやるモノではないので、記事共有のためだけになんか共有先以外のアカウント作らなくちゃいけないとか、なんかよく分からないサーバに情報送らないといけないとか、そういうのが必要になるサービスは避けたかった。一番良いのは、コードがオープンになっていて、ブラウザ内で操作が完結するようなもの。</dd>
<dt>何か問題があった時の対応がスムーズ</dt>
<dd>Mastodon は結構進化が早いのが特徴だと思っていて、これは良い反面色々壊れやすいという面もあると思う。そうなると自然、共有ボタン側も随時進化が必要になってくる。そういう問題に対しての対処が継続的に行われていく体制があるようなサービスがいいなという感じ。</dd>
</dl>
<p>一応上の記事に載ってるものは一通り試してみたんだけど、この点であまり満足がいくものがなかった。で、記事のシェアボタンのコードを読んだ感じ割と簡単に作れそうなので、どうせなら僕個人の需要に合わせた Web アプリ作ってみるかとなった。実際、基本的なコードは3時間ぐらいで動くものができたので、まあその程度っぽい。</p>
</div>
<div class="section" id="auto-id-2">
<h2>共有ボタンの仕組み<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>共有ボタンの使い方に関しては、<a class="reference external" href="https://mizunashi-mana.github.io/mastodon-front-gateway/add-share-button/">https://mizunashi-mana.github.io/mastodon-front-gateway/add-share-button/</a> を見てくれって感じ。ボタンの動作としては、</p>
<ol class="arabic simple">
<li><tt class="docutils literal"><span class="pre">https://mizunashi-mana.github.io/mastodon-front-gateway/share?text={{text}}&url={{url}}</span></tt> というリンクに飛ぶ</li>
<li>共有先の情報を入力する画面が開く</li>
<li>共有先の情報入力して共有ボタン押すと、 <tt class="docutils literal"><span class="pre">https://your.mastodon/share?text={{text}}&url={{url}}</span></tt> に飛ぶ</li>
</ol>
<p>という感じ。 <tt class="docutils literal"><span class="pre">https://mizunashi-mana.github.io/mastodon-front-gateway/share?text={{text}}&url={{url}}</span></tt> は完全にクライアントサイドだけで動くアプリとなっていて、共有ボタンを押すと、</p>
<ol class="arabic simple">
<li>ユーザIDが URL だったら、そのオリジンを共有先に設定</li>
<li>ユーザIDが URL じゃなかったら、ドメイン部分をパースして、そのドメインの <a class="reference external" href="https://docs.joinmastodon.org/spec/webfinger/">WebFinger</a> にアクセスしてユーザIDの情報を取得し、プロフィール URL のオリジンを共有先に設定</li>
<li>「ブラウザにユーザIDを保存」にチェックついてたら、ブラウザのローカルストレージにユーザID保存。次回、ローカルストレージからユーザID補完</li>
<li>共有先のオリジンの <tt class="docutils literal">/share</tt> をクエリパラメータ渡して開く</li>
</ol>
<p>みたいな挙動になる。これを JavaScript でやってる感じ。自動遷移機能というのもつけていて、これは単にローカルストレージにそういうオプション追加で保存して、次回開いた時ローカルストレージにそういうオプション載ってれば、自動で共有処理が走るだけ。自動遷移は、<a class="reference external" href="https://mizunashi-mana.github.io/mastodon-front-gateway/reset/">https://mizunashi-mana.github.io/mastodon-front-gateway/reset/</a> でリセットすれば解除できる。30日の有効期限もつけてるので、期間空いて解除の仕方分からんくなっても、多分大丈夫。</p>
<p>技術スタックとしては、</p>
<ul class="simple">
<li>View フレームワークは、 <a class="reference external" href="https://reactjs.org/">React</a>。これも慣れ。もうこれでいいじゃんってなって抜け出せない。</li>
<li>国際化対応フレームは、 <a class="reference external" href="https://www.i18next.com/">i18next</a>。これも慣れ。まあちょっと不便な点はあるが、基本これでいいなって感じ。</li>
<li>CSS フレームワークは、 <a class="reference external" href="https://tailwindui.com/components">Tailwind</a>。なんか慣れた。まあ、正直こんぐらいなら大人しく <tt class="docutils literal">style</tt> 直接書けばいいじゃんと思わなくはない。</li>
<li>フォントフレームワークは、 <a class="reference external" href="https://fontawesome.com/">FontAwesome</a>。レパートリー豊富だしね。ただ、最近 SVG の書き方覚えたので、簡単なのは自分で書けばいいじゃんってなってる。</li>
<li>バンドルツールは、 <a class="reference external" href="https://webpack.js.org/">webpack</a> 。これも慣れ。まあ、辛い点はあるが、そこまで大きく困ってることもない。というか、他も辛くて、満足いくものがない。</li>
</ul>
<p>という感じ。改めて書いてみると慣れがほとんどだな。その内時代に取り残されそう。</p>
<p>コードは、<a class="reference external" href="https://github.com/mizunashi-mana/mastodon-front-gateway">https://github.com/mizunashi-mana/mastodon-front-gateway</a> に公開してて、GitHub Pages へのデプロイ方法まで揃ってるんで、自分で立てたかったらフォークして適当に設定変えてどっかにデプロイして貰えばいいし、<a class="reference external" href="https://mizunashi-mana.github.io/mastodon-front-gateway/add-share-button/">https://mizunashi-mana.github.io/mastodon-front-gateway/add-share-button/</a> をそのまま使ってもらってもいいって感じ。CDN サービス契約して、CI さえなんとかすれば普通にそれだけで立つんで、ま、ご随意にという。</p>
<p>共有ボタン自体は、 <tt class="docutils literal">a</tt> タグでリンクすれば終わり。<a class="reference external" href="https://mizunashi-mana.github.io/mastodon-front-gateway/add-share-button/">https://mizunashi-mana.github.io/mastodon-front-gateway/add-share-button/</a> に一応幾つかサンプル載せてる。サンプルのロゴは公式から引っ張ってきて AGPL なので使いにくいかも。ま、その辺は好きに変えてくれ。というか、AGPL じゃないいい感じの再頒布条件の Mastodon ロゴ募集中です。コピーライトさえ載せてて、免責特記さえあれば、自由に再頒布可能とかだと嬉しい。</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、Mastodon への共有ボタン用の Web アプリ作ってみたので、仕組み紹介という感じだった。そして、共有ボタン追加してみた。是非、使ってみてくれ。以上。</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/03/mastodon-share-button.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/03/mastodon-share-button.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>双方向型検査: 検査と構築の融合2023-02-21T13:45:32+09:002023-03-04T07:46:57+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-02-21:/blog/posts/2023/02/bidirectional-typing/<p>単純型付きラムダ計算へ多相型を導入した拡張として System-F という体系がある。これは、通常の型付きラムダ項に、型の量 …</p><p>単純型付きラムダ計算へ多相型を導入した拡張として System-F という体系がある。これは、通常の型付きラムダ項に、型の量化と特殊化を行う構文拡張を加えたもので、有限の項で様々な型に対応する共通のプログラムを表現できるようになる。このような表現力の拡張は、理論上も応用上も重要であり、多くの研究が行われた。型推論も題材の一つになる。System-F はパラメータ多相、いわゆるジェネリック型をプログラミング言語に取り入れる際重要な基盤になることが期待され、この拡張へ型推論が提供できれば応用範囲はかなり広がるだろう。しかし、この問題については、Wells により型推論が決定不能であることが示され <a class="footnote-reference" href="#typability-of-system-f-is-undecidable" id="auto-id-2">[1]</a>、一つの決着がついている。</p>
<p>さて、このような背景から、System-F の型推論の研究は、完全な型推論は諦め、実用的な範囲の少し力を落とした型推論を考えるのが一般的だ。その中でも、推論方法のアプローチとして、大きく2つの流派がある。一つが、System-F そのものの機能を落としたある程度完全な型推論が行える体系を考えるというものだ。このアプローチにより、大きく成功を収めたのが HM 型システムと呼ばれる体系だ。HM 型システムでは、System-F の強力な型の抽象化の機能を実用的な範囲、特に制限をかなり加えた量化と特殊化が、抽象と適用が連なった構文要素の糖衣についてだけ行えるようにするといった体系に弱めることで、いわゆる完全な型推論とまではいかないまでも、型付け可能性のある項についてある程度代表的な型を推論できる方法を提供する。もう一つのアプローチは、System-F そのものの機能は落とさず、型推論ができる範囲を明示し、その範囲についてある程度実用的な型推論を行おうというものである。今回紹介する双方向型検査というのは、このアプローチにより推論を伴った型検査を提供する技術体系で、こちらも一定の成果を上げている。特に、HM 型システムは、結局のところ機能を制限した System-F とは異なる体系に焦点を当ててのアプローチだったが、こちらのアプローチは元の体系の機能自体は落とさないため、方法論自体は System-F 以外にも流用しやすい。実際、双方向型検査というのは、System-F の推論だけにとどまらず、依存型や積型・和型の入った体系など、かなり強力な機能が入った型システムについて、推論方法の基盤を提供してくれる <a class="footnote-reference" href="#practical-examples-of-bidir-typing" id="auto-id-3">[4]</a>。</p>
<p>双方向型検査では、型検査モードと型構築モード (型推論モード) という2種類のモードを用意し、この2つを随時切り替えながら、型検査と推論を連動させた型システムにより、型検査を行うことができる。今回は、この双方向型検査を (可述的) System-F の型推論で提供する方法を紹介する。題材は</p>
<blockquote>
Jana Dunfield and Neelakantan R. Krishnaswami. 2013. Complete and easy bidirectional typechecking for higher-rank polymorphism. In Proceedings of the 18th ACM SIGPLAN international conference on Functional programming, ACM, Boston Massachusetts USA, 429–442. DOI: <a class="reference external" href="https://doi.org/10.1145/2500365.2500582">https://doi.org/10.1145/2500365.2500582</a></blockquote>
<p>と</p>
<blockquote>
Simon Peyton Jones, Dimitrios Vytiniotis, Stephanie Weirich, and Mark Shields. 2007. Practical type inference for arbitrary-rank types. J. Funct. Prog. 17, 1 (January 2007), 1–82. DOI: <a class="reference external" href="https://doi.org/10.1017/S0956796806006034">https://doi.org/10.1017/S0956796806006034</a></blockquote>
<p>一つ目は、双方向型検査の権威 Dunfield 先生による、可述的 System-F への双方向型検査の提供について。もう一つは、お馴染み SPJ による可述的 System-F の型推論方法についての比較検討といった感じ。System-F の型推論については、SPJ の方の題材は読んでみると色々参考になるだろう。今回はそのうち、双方向型検査の部分だけ、扱っていく。</p>
<div class="section" id="system-f">
<h2>可述的 System-F<a class="headerlink" href="#system-f" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>System-F は元々、型の量化と特殊化の構文を入れた型付きラムダ計算だが、今回扱う言語では型推論を見据えて変数の型注釈を省略したり、明示的な特殊化ではなく型注釈から特殊化が自動的に行われるような体系を考える。具体的には、構文として以下のものを考える:</p>
<img alt="構文要素" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/syntax.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> は単相型、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> が通常の型、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> が項の構文となる。また、型システムの環境として、以下のものを使用する:</p>
<img alt="型環境" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/ctx-syntax.png"/>
<p>この時、以下の型システムを持つ言語が今回扱う対象になる:</p>
<img alt="型システム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/type-system.png"/>
<p>前半3つが型の妥当性判定、後半が型付け判定になる。最後の2つが、型の量化と特殊化に当たる。通常、パラメータ多相を含む言語は、型変数の動く範囲について単相型のみを割り当てられるか、割り当てる型に制約が特にないか、つまり多相型ですら型変数によって割り当てられるかにより、言語全体の能力や性質が大きく変わってくることが知られている。前者を可述的 (predicative) であるといい、後者を非可述的 (impredicative) であるという。型推論においてもこの違いは大きく、一般に非可述的な言語の方が型推論が難しい。System-F は可述的な体系、非可述的な体系、それぞれ存在するが、今回は双方向型検査の紹介が目的なので、比較的難易度が低い可述的な System-F を対象として扱っていく。可述性は型システムにより決まり、今回の型付け判定では最後の型の特殊化規則で、置換が単相型に制限されている部分が可述性を決定づけている。これを、単相型でなく型全般にすると非可述的な体系になる。</p>
<p>Wells の結果 <a class="footnote-reference" href="#typability-of-system-f-is-undecidable" id="auto-id-4">[1]</a> から、このシステムにおいて型付け可能性、つまり以下の問題は決定不能であることが知られている:</p>
<blockquote>
項 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⊢</mo><mi>e</mi><mo>:</mo><mi>σ</mi></mrow><annotation encoding="application/x-tex">\vdash e: \sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> となる <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> は存在するか?</blockquote>
<p>もちろん完全な型推論方法があれば、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> の存在性は示せるため、逆に言えば完全な型推論も決定不能ということになる。</p>
</div>
<div class="section" id="auto-id-5">
<h2>双方向型システム<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>これに対して、双方向型検査では、双方向の型システムを提供し、上記の型システムへの完全な型推論を諦める代わりに、双方向の型システムに対してはある程度完全な型推論アルゴリズムを提供する。双方向の型システムは以下のように定義される:</p>
<img alt="双方向型システム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/bidir-type-system.png"/>
<p>双方向型システムは2つの部分型関係 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\leq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⪯</mo></mrow><annotation encoding="application/x-tex">\preceq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">⪯</span></span></span></span></span> に依存するが、これについては後で見るとして、まずは双方向型システムの概要を見ていく。双方向型システムの判定は、</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi><mo>⊢</mo><mi>e</mi><mo>⇒</mo><mi>σ</mi></mrow><annotation encoding="application/x-tex">\Gamma \vdash e \Rightarrow \sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> は、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> の下で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> から型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> が構築される</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi><mo>⊢</mo><mi>e</mi><mo>⇐</mo><mi>σ</mi></mrow><annotation encoding="application/x-tex">\Gamma \vdash e \Leftarrow \sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇐</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> は、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> の下で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> は型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> で型付けできる</li>
</ul>
<p>と読む。なお、紛らわしいので、元々の双方向でない型システムによる型付け判定を単方向型付け判定と呼ぶことにし、双方向型システムの判定をそれぞれ単に構築判定、型付け判定と呼ぶことにする。まず、単方向型付け判定と双方向型システムの対応関係を見てみる <a class="footnote-reference" href="#completeness-of-bidirectional-typing-of-system-f" id="auto-id-6">[2]</a>:</p>
<img alt="双方向型システムの完全性" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/completeness-of-bidir-type-system.png"/>
<p>このように、双方の部分型関係が反射的であり、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\leq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span></span> が具体化を判定できるなら、ラムダ抽象、型の量化と特殊化に適宜型注釈をつけることで、元の型システムを尊重するような型構築ができる。この型注釈を適宜つけなければいけないというのが今回のポイントで、前述のように今回の対象言語は型注釈なしの項に対して決定可能な推論を提供できないため、今回の双方向型システムでは適宜型注釈を要求することで決定可能な範囲の推論にとどめるようになっている。これが完全な型推論を目指すアプローチと異なる部分になる。とは言っても、決定可能な範囲で推論を増強することは可能だ。例えば AbsSyn、AnnAbsSyn の規則は入れなくても単方向型付けとの対応は取れるが、これがない場合抽象に対して一々注釈を入れなくてはいけないようになってしまう。この後紹介する部分型関係の規則についても、決定可能な範囲で推論できる範囲を増やす為いくつか工夫が施されている。</p>
<p>さて、では部分型関係の方も見ていく。部分型関係はそれぞれ型の量化、具体化を自動でいい感じにやってくれるようなものになる。また、上記の話から反射性を満たし、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\leq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span></span> については具体化をサポートする必要がある。また、単方向型付け規則に対する健全性への制約から、型注釈を足す程度で変換できる範囲での関係にしておく必要がある。この条件を満たすような <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\leq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span></span> 構成としては、例えば以下のようなものがある:</p>
<img alt="部分型関係" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/subtyping.png"/>
<p>左が部分型関係の判定、右がその保証となる変換式になる。この定義であれば、変数、関数型はそのまま、多相型は Spec、Skol を組み合わせることで反射性を保証でき、特殊化もサポートしているため、条件を満たしている。さらに、この程度の判定であれば決定可能にできる。これについては後述する。<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⪯</mo></mrow><annotation encoding="application/x-tex">\preceq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">⪯</span></span></span></span></span> の方は、関数型への変換に特化した部分型関係となっており、適用の際暗黙的変換として使用される。こちらも、幾つかデザインの幅があると思うが、例えば以下のようなものがある:</p>
<img alt="適用のための暗黙的変換" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/subsumption.png"/>
<p>こちらは、基本的には型注釈をいい感じにつけて最終的に関数型に行きつくような範囲で、決定可能な判定が作れれば良い。例えば、以下のような判定を入れることもできる:</p>
<img alt="暗黙的変換の拡張" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/extension-of-subsumption.png"/>
<p>この拡張により、量化された型の構築ができる。まあ、今のところあまり有用な場面は思いついてないが、とりあえず関数型に行き着くような暗黙的変換の定義は色々できるという話。そこら辺は言語デザインに合わせて調整が必要になってくる部分だろう。ただ、暗黙的変換は一度採用してしまうとプログラマ側で変換を無効化すると言ったことができない。そこら辺は注意して設計するのが良いだろう。</p>
<p>さて、双方向型システムで型構築の導出をしてみた例が以下になる:</p>
<img alt="双方向型システムによる型構築導出" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/example-bidir-type-deriving.png"/>
<p>あまり型構築してるようには見えないかもしれないが、左から型を構築していき、構築した型を元に型付け判定をしていくのが基本的な流れだ。</p>
</div>
<div class="section" id="auto-id-7">
<h2>推論アルゴリズム<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、先ほどの導出例から分かる通り、双方向型システムはそれだけだと、アルゴリズミックに項に対して型を推論するのは難しい。ただし、この型システムに対して完全な、具体的に型を推論するアルゴリズムが構成可能だ。最後にこのアルゴリズムと、その構成の仕方を紹介しておく。</p>
<p>推論アルゴリズムの紹介に入る前に、まず型環境をアルゴリズム向けに拡張しておく:</p>
<img alt="推論アルゴリズム用の型環境" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/algorithmic-bidir-typing-context.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>α</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{\alpha}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span></span></span></span></span></span></span></span> はアルゴリズム中で生成される変数を表す。<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>α</mi><mo>^</mo></mover><mo>=</mo><mi>τ</mi></mrow><annotation encoding="application/x-tex">\hat{\alpha} = \tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> は、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>α</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{\alpha}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span></span></span></span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> と等価であるという制約を表す。<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>↦</mo><mover accent="true"><mi>α</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\alpha \mapsto \hat{\alpha}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.522em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span></span></span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>α</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{\alpha}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span></span></span></span></span></span></span></span> に置換されたことを表すマーカのような役割を持つ。詳細は、アルゴリズムを見ながら説明していく。もう一つ、アルゴリズムを説明する前に導入しておくものがある。それが型環境による置換だ:</p>
<img alt="推論アルゴリズム用の型環境による置換" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/algorithmic-bidir-context-subst.png"/>
<p>この置換では、環境内にある等価制約を使って、アルゴリズム中で生成された変数を置き換えていく。これをアルゴリズム中で適用していくことで、単一化の代わりにしているという感じだ。では、実際のアルゴリズムを見てみる:</p>
<img alt="推論アルゴリズム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/algorithmic-bidir-typing.png"/>
<p>相変わらず部分型関係の推論は後回しにすることにして、まずは判定の読み方だが</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi><mo>⊢</mo><mi>e</mi><mo>⇒</mo><mi>σ</mi><mo>∣</mo><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Gamma \vdash e \Rightarrow \sigma \mid \Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> は、環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> が与えられた時、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> を尊重するような環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> と型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> が構築される</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi><mo>⊢</mo><mi>e</mi><mo>⇐</mo><mi>σ</mi><mo>∣</mo><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Gamma \vdash e \Leftarrow \sigma \mid \Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇐</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> は、環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> が与えられた時、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> を尊重するような環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> の下で型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> に型付けできる</li>
</ul>
<p>という感じ。まあ、大雑把には、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> に新しく生成した変数やら制約やらを入れた <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> が出力され、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⇒</mo></mrow><annotation encoding="application/x-tex">\Rightarrow</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">⇒</span></span></span></span></span> ではさらに型も出力される、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⇐</mo></mrow><annotation encoding="application/x-tex">\Leftarrow</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">⇐</span></span></span></span></span> は型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> が入力となっており、型検査が通るかがチェックされるという感じだ。この入出力を押さえておくと、双方向型システムから割と機械的に上記のアルゴリズム的型判定は生成できる。例えば、Abs 規則は、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>e</mi></mrow><annotation encoding="application/x-tex">\lambda x\ldotp e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mn>1</mn></msub><mo>→</mo><msub><mi>σ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">\sigma_1 \to \sigma_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> が入力として与えられるので、そこから <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> に対してまた判定をかけて、出力の環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> を得るという感じ。なお、このアルゴリズム的型判定では環境の順序が大事で、基本的に変数が生成されて環境に突っ込まれた場合その変数に関する制約はその位置に突っ込まれるようになっているため、基本最終結果に使用する変数以外の環境情報はいらない。なので、環境に生成された変数以外の何かを最後に突っ込んでおくと、それ以降に突っ込まれたものは最終結果には影響しないことが保証される。これについては、この後の部分型関係の推論と導出例で詳しくみる。もう一つ、AbsSyn の例を見ておくと、この場合は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>e</mi></mrow><annotation encoding="application/x-tex">\lambda x\ldotp e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span></span></span></span></span> だけが入力となっている。この場合、型も頑張って作らないといけない。ただ、これは正直よく分からん。というわけで、ブラックボックスのまま推論を進めるため、変数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><msub><mi>α</mi><mn>1</mn></msub><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{\alpha_1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><msub><mi>α</mi><mn>2</mn></msub><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{\alpha_2}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> を当てがい、推論を進めてみて、その中で明らかになった制約を出力環境に保持したまま、生成した変数を使って出力の型を作るということをする。後は、出力に制約が含まれていたらそいつで置換、含まれていなかったら自由変数として放置すれば、いい感じの型になる。</p>
<p>さて、2つほどそもそも何が入出力かわからない部分があると思う。定義をまだ出していない部分型関係の推論を使っている、Sub規則、App規則だ。まず、Subの方だが、こいつは単一化兼一般化兼具体化みたいな役割担ってるやつで、環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span>、 型2つを入力として、その間に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\leq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span></span> の関係が成り立つような、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> を尊重する環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> を出力する。App規則の方は、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi><mo>⊢</mo><msub><mi>σ</mi><mn>1</mn></msub><mo>⪯</mo><msub><mi>σ</mi><mn>2</mn></msub><mo>→</mo><msub><mi>σ</mi><mn>3</mn></msub><mo>∣</mo><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Gamma \vdash \sigma_1 \preceq \sigma_2 \to \sigma_3 \mid \Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⪯</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> のうち、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">\sigma_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> が入力で、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">\sigma_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">\sigma_3</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> が出力になる。こいつも、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> を尊重するような <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> と、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi></mrow><annotation encoding="application/x-tex">\Delta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span></span> の下で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⪯</mo></mrow><annotation encoding="application/x-tex">\preceq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">⪯</span></span></span></span></span> の関係が成り立つような <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">\sigma_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span>、 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">\sigma_3</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を計算するのが役割だ。</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⪯</mo></mrow><annotation encoding="application/x-tex">\preceq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">⪯</span></span></span></span></span> の方が簡単なので、まずそちらから見てみる:</p>
<img alt="暗黙的型変換の決定" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/algorithmic-subsumption.png"/>
<p>Refl は良い。Spec は元の規則通りだが、どういう具体化するか分からんので、そこを変数作ってブラックボックス化して凌ぐ感じ。で、元にない Unify というのが追加されているが、これが生成された変数にぶち当たった時用のやつで、この場合関数型になることだけ分かるので、関数型との等価制約だけ入れて、後の方はブラックボックスにして後続の推論におまかせという感じだ。ここで、制約を入れる位置が重要で、前述の通り元々の変数があった位置に入れることで、変数のスコープを調整している。</p>
<p>次に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\leq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span></span> を見る。こちらはやや複雑:</p>
<img alt="部分型関係の推論" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/algorithmic-subtyping.png"/>
<p>前半が部分型の検査、後半がそれに伴う単一化という感じだ。前半はまあいいだろう。後半も実際はそれほど難しいことはしてなくて、単相型ならそのまま単一化、それ以外の場合は生成された変数か、関数型か、量化された型のいずれかなので、それぞれに規則があるという感じ。変数の場合は、環境の出現位置で順序をつけて、出現が早い方に単一化し、関数型の場合は両辺それぞれを単一化する。量化されてる型の場合だけ特殊で、この場合はどちらに量化された型が現れるかで Spec、Skol どちらの規則に合わせるかが変わるので、それぞれ調整している感じ。</p>
<p>こんな感じでやれば双方向型システムに対してある程度完全な推論がアルゴリズミックにできる。ある程度というのは、多少抽象度が高い推論をしてしまうことがあるかもしれないということで、残った変数に適宜型を割り当てられると完全になるみたいな感じ。さて、では実際に導出例を見てみる:</p>
<img alt="推論アルゴリズムによる導出例" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/bidirectional-typing/bidirectional-typing/example-algorithmic-bidir-type-deriving.png"/>
<p>基本、推論に使う規則選びつつ、左から順にそのまま規則を適用していけば自然に導出が完成している。導出が完成しなければ推論失敗という感じ。あとは、規則を決定的にしてやれば、アルゴリズムになる。また、元の双方向型システムでの導出例と対応が取れてることも分かるだろう。このようにちゃんと規則が対応して適用できるようになっているため、完全な推論ができるという感じだ。完全性の証明は、題材には載ってないが Dunfield 先生が別途公開していて、<a class="reference external" href="https://research.cs.queensu.ca/home/jana/papers/bidir/">https://research.cs.queensu.ca/home/jana/papers/bidir/</a> の Proofs から見れる。興味があれば見てみると良いだろう。</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、System-F の推論を考慮した双方向の型システムと、それに対する完全な推論アルゴリズムを紹介した。完全な推論はあれば便利だが、完全な推論ができない体系について言語の機能を落とさずにある程度実用的な推論を提供できるのは実用的には嬉しそうだ。ただ、双方向型システムは理論的にも面白いと思っていて、基本的に型推論の文脈では任意の項について主要型 (principal type) を見つける話から始まるわけだが、双方向型システムは主要型が決まる項と決めるのが難しい項を意味論として形式化できる能力があるところが面白いと思う。今回の System-F では、量化された型の導入は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⇐</mo></mrow><annotation encoding="application/x-tex">\Leftarrow</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">⇐</span></span></span></span></span> の判定しか持たない。逆に適用は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⇒</mo></mrow><annotation encoding="application/x-tex">\Rightarrow</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">⇒</span></span></span></span></span> しか持たない。これはそれぞれ、量化された型の導入について型付け判定はできるが主要型の探索は難しい、適用は部分項の型が決まれば主要型が自然に決まるみたいな性質に対応する。ここら辺は、一般的な (単方向の) 型付け判定より、言語の型のモデルをよく捉えられていると言えそうで、結構面白いなと思った。なお、じゃあ何かしら言語があった時、双方向の型システムをどうやって構成していけばいいかについては、</p>
<blockquote>
Jana Dunfield and Neel Krishnaswami. 2022. Bidirectional Typing. ACM Comput. Surv. 54, 5 (June 2022), 1–38. DOI: <a class="reference external" href="https://doi.org/10.1145/3450952">https://doi.org/10.1145/3450952</a></blockquote>
<p>で、Dunfield 先生が step-by-step で解説してくれてる。これは割と参考になると思うので読んでみると良いんじゃないだろうか。</p>
<p>ところで、実はこの記事を書いたのは <a class="reference external" href="https://www.haskellforall.com/2022/06/the-appeal-of-bidirectional-type.html">The appeal of bidirectional type-checking</a> という記事がきっかけだった。この記事は「HM 推論はもう古い、これからは双方向型検査の時代!」という感じの文面 <a class="footnote-reference" href="#a-nuance-of-the-appeal-of-bidirectional-type-checking" id="auto-id-9">[3]</a> で、まあそうなのかと乗せられた感じだ。ただ、導入部分で説明したように、そもそも HM 推論と双方向型検査ではかなりアプローチも達成できることも異なる。それに、HM 推論は具体的な体系に対する推論だが、双方向検査はより一般的な双方向の型システムに対しての検査を指す総称なので、比較対象としても成り立つかと言われると微妙だ。そして、双方向型システムをちゃんと一から構成するのはかなり難易度が高いと個人的には思う。なので、HM 推論周りの応用技術が使える範囲で済むなら、別に双方向型システムの方を採用する意義は薄そうだと思う。ただ、型システムをどんどん拡張していき、結構強い型の機能を入れていくなら、双方向型システムでモデル化してそこからアルゴリズムを作っていくのは結構合ってそうだ。別に難易度は易しくはないと思うが、無理に HM 推論を拡張するより扱いやすそうな印象がある (実用経験なしの言葉)。ま、一度触れてみて、HM 推論はもう古いとか言ってる人尻目に、自分の言語に合いそうだったら使っていくのがいいんじゃないだろうか。</p>
<p>ま、そんな感じで。今回はこれで。</p>
<table class="docutils footnote" frame="void" id="typability-of-system-f-is-undecidable" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label">[1]</td><td><em>(<a class="fn-backref" href="#auto-id-2">1</a>, <a class="fn-backref" href="#auto-id-4">2</a>)</em> J.B. Wells. 1999. Typability and type checking in System F are equivalent and undecidable. Annals of Pure and Applied Logic 98, 1–3 (June 1999), 111–156. DOI: <a class="reference external" href="https://doi.org/10.1016/S0168-0072(98)00047-5">https://doi.org/10.1016/S0168-0072(98)00047-5</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="completeness-of-bidirectional-typing-of-system-f" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[2]</a></td><td>これは Dunfield 先生の方の題材では完全性として提示されている関係性。題材には、証明は載っていないが、<a class="reference external" href="https://research.cs.queensu.ca/home/jana/papers/bidir/Dunfield13_proofs.pdf">https://research.cs.queensu.ca/home/jana/papers/bidir/Dunfield13_proofs.pdf</a> に証明が載っており、そこから復元したものになる。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="a-nuance-of-the-appeal-of-bidirectional-type-checking" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-9">[3]</a></td><td>まあ、そこまでは言ってないかもだが、ニュアンス的にはそんな感じの印象が強い。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="practical-examples-of-bidir-typing" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[4]</a></td><td>元々 Scala や Agda を事例に出してたが、どちらも双方向型システムによるアルゴリズムは型検査に使ってなさそうだったので、訂正した。申し訳ない。</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/03/bidirectional-typing.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/03/bidirectional-typing.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Mastodon 体験記2023-02-18T15:58:46+09:002023-02-18T15:58:46+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-02-18:/blog/posts/2023/02/mastodon-experience/<p>Twitter から Mastodon に移住して一ヶ月ほど経ち、あんまり Twitter に戻る気がなくなってきた。せっかくなので、備忘録と案内を兼ねて …</p><p>Twitter から Mastodon に移住して一ヶ月ほど経ち、あんまり Twitter に戻る気がなくなってきた。せっかくなので、備忘録と案内を兼ねて、Mastodon への移住経緯とその後のことや、いろいろ感想などをまとめておこうと思う。とりあえず、一言で言うと Twitter には多分戻らんと思うのでよろしくという感じ。</p>
<div class="section" id="auto-id-1">
<h2>Mastodon への移住<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>正直きっかけは今でもよく分からない。2023/01/30 に毎度ながら Twitter を開いて TL を見てたんだが、ふと寂しさを覚えた。割と、流速は速かったと思うので人がいなかったわけでも無さそう。そもそも「フォロー中」のタブが増えてから、割と Twitter で寂しさを覚えることは多かった。凍結騒動で色んな人が凍結され Mastodon に行ったみたいなことも聞いていたので、なんかあまり「フォロー中」のタブの人口がいないことが原因なんじゃないかみたいなのを思ったりした。自分が知らない間にみんな Mastodon に移行しており、僕だけ Twitter に取り残されてるんじゃないかという焦りが生まれ、とりあえず Mastodon を覗いてみることにしたという感じだ。これが最初のきっかけ。なお、実際に Mastodon に移行してみて分かったことだが、それほど移行した人は多くなく、Twitter の方がまだまだ人口は多い。つまり、寂しさの原因は人口ではないということだ。これについては後で考察する。とりあえず、きっかけはそんな雑な感じだ。</p>
<p>さて、そもそも僕は Mastodon にあまり興味がなかった。3年前くらいに話題になった時、アカウントを作って見たことはあった。が、使い方がよく分からなくて、それを調べるモチベもあまり生まれず、そのまま放置していたという感じだ。なんかサーバが各自で立てられる、Twitter 似の単文 SNS ぐらいの認識で、Mastodon に参入したわけだ。3年前くらいに作ったアカウントをそのまま動かす気にはなれず、少し前から気になっていた Vivaldi Social (<a class="reference external" href="https://social.vivaldi.net/">https://social.vivaldi.net/</a>) というところにアカウントを作ってみることにした。さて、ここで予備知識、というか僕は Vivaldi Social に入ってから身につけた知識だが、Mastodon というのはサーバソフトウェアの名前だ。GitHub 上に AGPL 3 or later でソースが公開されており、多数のコントリビュータによって開発されている。このサーバソフトウェアをインストールし、運用されているサーバが Mastodon インスタンスと呼ばれるもので、世界に無数にあるし、それぞれ入っているソフトウェアのバージョンも、管理人も、運用環境も異なる。中には、プログラムに独自の手が加えられたものも存在する。このようなインスタンスそれぞれに、ユーザがおり、それぞれ相互にやり取りをしている。<a class="reference external" href="https://github.com/mastodon/mastodon">公式</a> の可愛らしいイメージを拝借してくると、以下のような状況というわけだ:</p>
<img alt="Mastodon の公式イメージ (AGPLv3 Licensed)" class="align-center" src="https://camo.githubusercontent.com/d34a13f7f5e15d1ae46d5920f85973f19e1238adae8cbba5989e71b273179f37/68747470733a2f2f626c6f672e6a6f696e6d6173746f646f6e2e6f72672f323031382f30362f7768792d61637469766974797075622d69732d7468652d6675747572652f657a6769662d322d363066316230303430332e676966"/>
<p>Vivaldi Social はそうしたインスタンスの中の一つで、ブラウザでお馴染み Vivaldi が管理する Mastodon インスタンスだ。Vivaldi アカウントがあれば利用できる。Vivaldi ブラウザでは、サイドメニューに標準で自己主張激しめの Vivaldi Social へのリンクが置かれている。Vivaldi は利用することがたまにあり、信頼感は少しあって、まああとは成り行きで Vivaldi Social を利用することにした。それまでアカウントは作る必要性を感じてなかったので作ってなかったが、この機会に作った。なお、Mastodon インスタンスは他にもたくさんある。例えば、僕の知ってるものでは以下のようなものがある:</p>
<dl class="docutils">
<dt>Mastodon開発チーム運用鯖 (<a class="reference external" href="https://mastodon.social/">https://mastodon.social/</a>)</dt>
<dd>Mastodon開発チームが運用するインスタンス。誰でも歓迎。時々新規登録を閉鎖している。</dd>
<dt>Mastodon日本鯖 (<a class="reference external" href="https://mstdn.jp/">https://mstdn.jp/</a>)</dt>
<dd>元々、ぬるかるさんという方が個人で運用していたインスタンスで、誰でも歓迎というスタンスのインスタンス。ユーザ数が多く、また色々管理人が変遷していて、サーバ運用の難しさを感じる。</dd>
<dt>Pawoo (<a class="reference external" href="https://pawoo.net/">https://pawoo.net/</a>)</dt>
<dd>Pixiv が作ったインスタンス。創作活動推しで、ユーザ数が多く、やはり色々管理人が変遷している。</dd>
<dt>Fedibird (<a class="reference external" href="https://fedibird.com/">https://fedibird.com/</a>)</dt>
<dd>のえるさんという方が運用するインスタンス。Mastodon に独自の機能を色々加えたサーバを運用しているのが特徴。</dd>
<dt>Medium鯖 (<a class="reference external" href="https://me.dm/">https://me.dm/</a>)</dt>
<dd>ブログサービスでお馴染みの Medium が最近立ち上げたインスタンス。</dd>
<dt>セキュリティ情報共有鯖 (<a class="reference external" href="https://infosec.exchange/">https://infosec.exchange/</a>)</dt>
<dd>情報セキュリティ界隈の人たちが集まるインスタンス。Signal といい、情報セキュリティ界隈の人にはやっぱ透明性が担保されたツールへの需要があり、Mastodon はそこにマッチしたという感じか。</dd>
</dl>
<p>他にも多数の鯖があるし、個人で鯖を立てて SNS に参加している人も多い。僕はそんな壮大なネットワークの一角に参加したというわけだ。ネットは広大だわ。で、Vivaldi Social に入ってみた。以下は Vivaldi Social の画面:</p>
<img alt="Vivaldi Social の画面" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/mastodon-experience/mastodon-experience/vivaldi-social-screenshot.png"/>
<p>今は面影はないが、当初はサイドメニューにあるホームのページが開いており、何も表示するものがない旨が表示されていたと思う。僕は最初、とりあえずサイドメニューにある項目を次々と開いていった。そうすると、2つだけ何かしらが表示される項目があった。それが「ローカル」ってやつと「連合」ってやつ。調べたところによると、Mastodon には Twitter と違って4つのタイムラインがあるらしい:</p>
<dl class="docutils">
<dt>ホーム (HTL)</dt>
<dd>自分専用のタイムライン。自分のトゥート (Twitter でいうツイート) やフォローしてる人のトゥート、フォローしてる人がブースト (Twitter でいうリツイート) したトゥートが流れてくる。Twitter の「フォロー中」のタイムラインと同じ。</dd>
<dt>ローカル (LTL)</dt>
<dd>インスタンスのタイムライン。そのインスタンスに参加している人のトゥートが流れてくる。</dd>
<dt>連合 (FTL)</dt>
<dd>インスタンスに繋がっているユーザのタイムライン。ローカルに加えて、インスタンス内のユーザからフォローで辿った先のユーザのトゥートも流れてくる。自分が所属するインスタンス以外のインスタンスを、自分から見てリモートインスタンスというが、連合は自分が所属するインスタンス内の誰かがフォローしていれば、リモートインスタンスのトゥートも流れてくるというわけだ。これは、インスタンスから見たネットワーク全体のタイムラインということになるだろう。</dd>
<dt>ハッシュタグ</dt>
<dd>これは、上記サイドメニューに直接は項目としてないが、「エクスプローラ」という項目から辿った先のハッシュタグから覗けるタイムライン。Twitter のハッシュタグなどと同じく、ハッシュタグをつけた連合内のトゥートが流れてくる。活用方法は後述する。</dd>
</dl>
<p>というわけで、ホームは伽藍堂でハッシュタグは仕組みをあまり知らず、結果ローカルと連合でなんか流れてるなーと眺めてる存在になった。で、数分間そうしてなんとなく探検は終わった感があったので、トゥートをしてみることにした。記念すべき第一トゥートはこちら:</p>
<p><a class="reference external" href="https://social.vivaldi.net/@mizunashi/109778117918755023">https://social.vivaldi.net/@mizunashi/109778117918755023</a></p>
<img alt="記念すべき第一トゥート" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/mastodon-experience/mastodon-experience/first-toot.png"/>
<p>ところでこのトゥートを見てみると星マークに 5 という数字が並んでいるのが分かると思う。これは Twitter のいいねと同じ、お気に入り登録を 5 人のユーザがしてくれたということを表している。フォロワーが誰もいないのにお気に入りが 5 個付くのは、LTL / FTL がある Mastodon ならではだろう。ただ、僕は最初そもそも LTL / FTL などという仕組みすら知らなかったので、多少慌てた。どうやら、僕の雑な何気ないトゥートは不特定多数の人に見られたようだ。何も気づかないでこのままやべートゥート連発していたら、大惨事だ。さて、Mastodon は流石に全トゥートが LTL に流れるわけではない。トゥートの公開範囲は制御できるし、それも Twitter よりかなり細かく制御できる。Mastodon にはまずトゥート自体に以下の 4 つの公開範囲を設定できる <a class="footnote-reference" href="#mastodon-doc-privacy" id="auto-id-3">[1]</a>:</p>
<dl class="docutils">
<dt>公開</dt>
<dd>ログインしてない人でもパーマリンクを知っていれば見れる。僕の第一トゥートはこれになっていた。通常地球儀マークが表示される。フォロワーの HTL に配信される他、LTL / FTL にも配信される。誰でも自由にブーストできる。</dd>
<dt>未収載</dt>
<dd>基本公開と同じだが、LTL / FTL には配信されない。錠が外れた南京錠マークが表示される。</dd>
<dt>フォロワー限定</dt>
<dd>名前の通り基本フォロワーだけしか見れない。基本というのは、メンションした人にも特別に見れる仕様らしいので。フォロワーの HTL とメンションした人の通知欄にのみ配信される。自分以外はブーストできない。Mastodon でも Twitter の鍵垢と同じくフォローを承認制にすることができ、そうすると自分が承認した人しか見れないようになる。だが、承認制にしない場合はフォローは自由にできるので、フォロワー限定は基本見ようと思えば見れる。なお、名称が途中で変わったらしく、非公開という単語が昔は使われていたっぽい。こっちを使っている界隈もまだ結構あるようだ。</dd>
<dt>ダイレクト</dt>
<dd>Twitter の DM とほぼ同じだが、Mastodon では通常のトゥートと区別がないようだ。メンションした人にだけ見れる。メンションした人の通知欄にのみ配信され、ブーストはできない。Twitter と同じく UI 的にはタイムラインが分かれているようだ。使ったことがないので使い勝手は分からない。</dd>
</dl>
<p>これはトゥートごとに設定でき、トゥートする時に変更できる。もちろんデフォルトの公開範囲設定もあり、ユーザ設定で指定できる。Vivaldi Social では、以下の設定ができた:</p>
<img alt="プライバシー関連のユーザ設定項目" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/mastodon-experience/mastodon-experience/user-privacy-settings.png"/>
<p>これは僕の設定だが、個々人にあった設定をまずは行うのが良いだろう。僕は第一トゥートの後慌ててこの設定項目を見つけ、色々設定できることを知った (行き当たりばったりライフ)。無事公開設定を理解し、意識的に公開を選んでのトゥートが以下:</p>
<p><a class="reference external" href="https://social.vivaldi.net/@mizunashi/109778240439598295">https://social.vivaldi.net/@mizunashi/109778240439598295</a></p>
<img alt="三番目のトゥート" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/mastodon-experience/mastodon-experience/third-toot.png"/>
<p>これで無事挨拶を終え、その後はネットの海で未収載設定で潜伏しつつ、好き勝手なことを人様の迷惑を考えず垂れ流している。</p>
<p>さて、初日にもう一つやったことがフォローを増やして HTL を拡充させることだ。一番最初のフォローは、おすすめユーザという欄で唯一知っていた「数学ガール」作者の「結城浩」さん。とりあえずフォローポチっておいた。その後は、Twitter でアカウント開設告知しつつ Masaki Hara さんとかのフォロー欄から辿ってって見たことあるアイコンをフォローしていき、またそのフォロー欄辿るみたいなことしてた。もっといい方法あるのかもしれないが、今もその戦略とって人探してる。初日はそんな感じで終わった。</p>
<p>2日目はクライアント探し。Mastodon がサーバソフトウェアであることは言ったが、こいつには標準の Web UI も付属でついている。ただ、外部クライアント用の API も用意してあり、自由にクライアントソフトウェアを作成してそこでタイムラインを覗いたり、フォロー、トゥートなどが行える。まず、PC 用のクライアントとして TheDesk (<a class="reference external" href="https://thedesk.top/">https://thedesk.top/</a>) というクライアントソフトウェアを見つけ、インストールしてみた。これは今でも愛用しており、非常にお世話になっている。今の僕の TheDesk の画面はこんな感じ:</p>
<img alt="僕の TheDesk の表示" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/mastodon-experience/mastodon-experience/thedesk-screenshot.png"/>
<p>このように Tweetdeck のような、あるいはそれより複雑なタイムライン表示ができる。ローカルは、人がいて常に色々会話されていて、SNS に人がいることを実感できるので表示している。フォローが少ない時は重宝していたが、最近はなくてもいいかなという気持ちになりつつはある。他はリストという機能を使っていて、これについては後で少し触れる。</p>
<p>デスクトップ版はこれでいいかなとなって、モバイル版もいくつか探した。iOS は色々探したり教えてもらったりして Ivory にいきつき、とりあえずこれを使ってみている。Ivory は Tweetbot の開発元が作成した iOS 版クライアントソフトウェアで、インストール・閲覧だけなら無料ででき、投稿などは有料のサブスクリプションが必要になる。とりあえず、僕はサブスクリプションには入らないで閲覧機能だけ使っている。使い勝手やデザイン的には、Twitter の公式アプリとあまり変わらない。Android の方は Subway Tooter というアプリを使っている。このアプリは結構癖があるが、個人的にはアクセスしている API がローディング時に表示されることが魅力的で使っている。これはソフトウェア技術者ならではの感性な気がするが、ログが出ているとなんとなくやっていることが分かって安心感がある。基本的な機能も揃っているため、機能面で困ることはあまりない。ただ、やっぱりモバイル向けだとデザイン面で辛いことが多いというのはある。画面が小さいし、タップでの操作が基本になるが、結構要素が多くて誤タップなどを誘発しがち。そこの操作感は微妙に感じることはある。とりあえず、基本は TheDesk を常用してるので、モバイル版はあまり使い込んでなく、不満を持つ機会が少ないというのはある。その内感想が変わっていくのかもしれない。</p>
<p>その後はフォロー増やしたり、色々調べたり、時折トゥートしたりしてしばし過ごす。そんな中で探していたのが、ニュース系のbotアカウント。僕は Twitter は最近 SNS というより社会情勢を知る道具として使っていたところがあった。そこら辺の機能の代替が欲しかったわけだ。その結果見つけたのが以下のアカウント達:</p>
<dl class="docutils">
<dt>特務機関NERV (<a class="reference external" href="https://unnerv.jp/about/more">https://unnerv.jp/about/more</a>)</dt>
<dd>Twitter でフォローしてる人も割といるんじゃないかと思うが、災害情報、鉄道情報、NHK ニュース速報などを配信しているボットアカウント。Mastodon では <a class="reference external" href="https://unnerv.jp/@UN_NERV">https://unnerv.jp/@UN_NERV</a> を起点に、情報ごとにブーストするアカウント群があり、そちらをフォローすれば気になる情報だけ購読できるようだ。元ネタは新世紀エヴァンゲリオン。</dd>
<dt>毎日新聞ニュースbot (<a class="reference external" href="https://u-tokyo.social/@mainichi_bot">https://u-tokyo.social/@mainichi_bot</a>)</dt>
<dd>毎日新聞のニュース速報 RSS を配信しているボットアカウント。</dd>
<dt>震度速報 (<a class="reference external" href="https://mastodon.social/@quaketelop">https://mastodon.social/@quaketelop</a>)</dt>
<dd>気象庁の速報情報をもとに、地震の震度速報を配信しているボットアカウント。</dd>
<dt>News Selection (<a class="reference external" href="https://mastodon.social/@newsselection">https://mastodon.social/@newsselection</a>)</dt>
<dd>Twitter で話題になったニュースを配信してるボットアカウント。出自はいまいち分からん。</dd>
</dl>
<p>他にゲーム情報や為替情報を配信しているボットアカウントなども探したけど、見つからんかった (というか探し方がよく分からんかった) のでとりあえずこれだけフォローしてる。自分で作ってみるのもありだなあとは思っている。で、そういうボットアカウントをフォローしまくると、HTL がかなりごちゃごちゃしてくる。そこでリスト機能を使い始めるようになった。リストは Twitter のリストと基本同じだが、非公開リストしか作れないっぽい。後、リストにはユーザを追加してからのトゥートしか保持されない。僕はとりあえずメインのリスト作って、基本そっちの TL を見てる。TheDesk で HTL も置いといて、そこに流れてくるのでメインに入れたいなと思ったやつはメインに入れてる。モバイルとかではメインリストのしか基本見ないかな。</p>
<p>さて、そんなこんなで色々環境を整備しつつ TL を見ていた Mastodon 生活一週間目ぐらい、ようやく実はこの SNS に繋がっているのは Mastodon インスタンスだけではないことが分かってきた。どうやら僕が参加した世界は、W3C で標準化された ActivityPub というプロトコルでやりとりするサーバが、群雄割拠しているネットワークだった。そして、そこにいるサーバは Mastodon インスタンスだけではなく、他にも様々なサーバがいて、それぞれに特色を持っていた。僕が参加しているネットワークは Mastodon ネットワークではなく、ActivityPub による Fediverse という名前のネットワークだったっぽい:</p>
<img alt="Fediverse の外観" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/mastodon-experience/mastodon-experience/fediverse-overview.png"/>
<p>Fediverse には Mastodon 以外にも様々なサーバソフトウェアが繋がっている。主に僕が知っているものが以下:</p>
<dl class="docutils">
<dt>Misskey</dt>
<dd>最近有名なので知っている方も多いと思うが、しゅいろさん (<a class="reference external" href="https://misskey.io/@syuilo">https://misskey.io/@syuilo</a>) という日本の方が作成、メインで開発しているやっぱり Twitter 風のソフトウェア。日本人開発者がメインということもあり、サーバの運用者、登録者も日本人が多い印象がある。個人的には、他の ActivityPub サーバに比べ先をいっている印象があるが、僕は使ったことないので詳しいことは分からない。</dd>
<dt>Pleroma</dt>
<dd>Elixir で開発されている Twitter 風のソフトウェア。Mastodon などと比べて軽量という噂。やっぱりよく知らない。</dd>
<dt>GNU Social</dt>
<dd>結構歴史が古めの Twitter 風のソフトウェア。お馴染み Free Software Foundation 管理。ただ、あまり開発が活発ではなく、バグも多いようだ。</dd>
<dt>Pixelfed</dt>
<dd>Instagram 風の写真特化型 SNS ソフトウェア。そもそも僕はインスタやったことがないので、使い勝手がまるで想像できない。</dd>
<dt>Frendica</dt>
<dd>Facebook 風の SNS ソフトウェア。こっちも僕は Facebook やったことがないので、使い勝手がまるで想像できない。</dd>
<dt>Wildebeest</dt>
<dd>最近 Cloudflare が出してきた Mastodon 互換のソフトウェア。ActivityPub は基本相互のやり取り、フォローなどの基本的な機能しか策定されていないため、ここまで上げたソフトウェア達はそれぞれ独自に ActivityPub を拡張している。Mastodon ももちろん独自拡張を加えており、それに対応しているというのが Wildebeest の特徴になる。まだ出たばかりで機能が薄いという噂。</dd>
</dl>
<p>もちろん Fediverse に繋がっている人の中には、自身で一からサーバ書いて繋げてる人などもいるし、それぞれのソフトウェアをフォークして、独自の機能を追加している人などもいる。うまく繋がっていないサーバもいれば、協調路線を組んでいるサーバもいるし、それぞれが独立ながら相互に協調して発展していっているというのが現状のようだ。これは僕にとってはかなり衝撃的で、しかも魅力的だった。そもそもこの頃には、僕は Mastodon には様々な Twitter の未来をいく機能があることを知り、あまり Twitter に戻る気がなくなっていた。ところが、さらに Mastodon の機能の未来をいくソフトウェアや、全く毛色の異なるソフトウェアがネットワーク内には色々いたのだ。しかも、それにも不満があれば、自分でサーバを書き、それを繋げられる。これは Twitter やインスタ、Facebook、Tiktok などには成し得ない世界だろう。さらには、Tumblr が ActivityPub 対応を匂わせており、商用サービスが標準化されたプロトコルを喋ってくる日がくる可能性もある。</p>
<p>さて、ここまで Mastodon と Fediverse の世界に感銘を受け、毎日が感動の連続みたいな感じだったが、もちろん Fediverse は理想の世界ではなく現実のものであり、素晴らしい構想と発展性の影には、様々な問題も存在している。詳しくは後述する。さて、始めて2週間ぐらい、Fediverse のメタ的な話題を追うために、鯖缶や開発者などをフォローして TL を追うようになって分かってきたのは、Fediverse ノードの管理者は癖が強い人が多いということだ。実は正直なところ、Mastodon を始める前、僕が Mastodon に抱いていた印象は、機能は Twitter 劣化だが、分散的で、自由で、寛容というものだった。これは基本的に Twitter アンチテーゼとして生まれたという喧伝の影響が強いのだろう。ところが、Vivaldi Social で生活しているうちに、これはほぼ詐欺であることが分かってきた。</p>
<p>実際には、Fediverse も Twitter と同様ポリコレに侵されており、当然法の下での秩序を保つ義務があり、モデレーションが行われている。さらには、Fediverse ノードは個人の運用者が多く、Twitter のようにコストもあまりかけられないし、感情で動く人も多い。結果、治安は個々個人の裁量と妥協に委ねられることになる。これは、時に Twitter よりも強い縛りをもたらすことも多い。もちろん、それに不満があれば、個人のインスタンスを立てたり、他のノードに移ると言ったことは可能で、実際これを盾に個々の価値観で強権的な規則を敷くノードも多い。ただ、個人のインスタンスを立てたり、他のノードに移ることには、もちろんそれなりのコストとリスクが伴う。Fediverse の自由とは、あくまでそれなりの対価を支払う覚悟がある人にもたらされるものであり、寛容とは寛容でいられる範囲であれば寛容というわけだ。実際、このような実態は幾つか問題を起こしている。有名なものが Pawoo 国交断絶事件 <a class="footnote-reference" href="#pawoo-domain-block" id="auto-id-4">[2]</a> だが、Fediverse 界ではその手の事件が日夜起きている。まあ、Twitter などと違って、管理人が星の数いるわけだ。その分トラブルの種も多いのは当然と言えるだろう。また、これらのトラブルに嫌気がさしたり、コストに見合わないとして、多くの管理者が撤退している。</p>
<p>さらに、Fediverse はかなり薄氷の上に立っているという印象もある。皮肉なことに分散的に各個人がノードを建てることにより、「規模の経済」の法則が効かなくなり、全体的に Fediverse 運用コストは上がっている印象がある。運用コストが上がるということは、同じコストで運用できる機能が限られるということで、機能の中には冗長性とか安定性といったものも含まれる。つまり、分散的な Fediverse は、中央集権的な Twitter よりも脆弱で不安定であるということだ。もちろん、これらの問題を解決すべく、いろいろな取り組みはあるが、あまり解決に至っている印象はない。実際、この数週間の中で Pawoo がかなり不安定になり、一時接続できない状態になり、多数のユーザが他のノードに流入する事件があった。結果、他のノードもリソース増強を迫られる事態となった。結果的にこれは商用サービスにとっては好機となったと言えるだろう。</p>
<p>ここまでの一連の流れを見た僕の、Fediverse に参入して2週間目のトゥートがこちら:</p>
<p><a class="reference external" href="https://social.vivaldi.net/@mizunashi/109851262694371031">https://social.vivaldi.net/@mizunashi/109851262694371031</a></p>
<img alt="Fediverse の宣伝に関する感想" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/mastodon-experience/mastodon-experience/fediverse-thoughts-toot.png"/>
<p>で、Fediverse に嫌気が刺したかって? 別にそんなことはない。今や Twitter も安定的ではないし、Fediverse の各サービスが Twitter 風のサービスを独自に発展させ、かなり魅力的な世界を構築していることは揺るがないわけで、Fediverse の政治的な問題とは一線を画しつつこの魅力的なネットワークに参入する価値はあるだろうと思っている。</p>
<p>さて、こうして時間はどんどんこの記事を執筆している時間帯へと近づいてくるわけだ。さて、最近はある程度 Mastodon の使い勝手が分かってきて、純粋に Fediverse の世界を楽しみつつある。ただ、新しい発見が全くなくなったわけじゃない。最近ようやく分かってきたのが、公開トゥートとハッシュタグの活用法についてだ。</p>
<p>僕は基本これまで未収載トゥートしかしてきてない。最初の右も左も分からない状態での公開トゥートはともかく、僕の中ではあまり公開トゥートでフォロワー以外に情報発信をするモチベはなかった。また、Vivaldi Social は割と LTL での会話が発展していて、常に一部日本人同士で公開トゥートでのやり取りが行われている。これは見てて楽しいが、僕にとっては参入するモチベはあまりなかった。公開トゥートを行うと、自然 LTL にトゥートが流れるため、LTL の会話を遮ってしまうことになる。そうまでして何か公開トゥートがしたいという動機がなかったのだ。ただ、最近この動機をハッシュタグに見つけつつある。</p>
<p>ハッシュタグタイムラインは、テーマを絞ったタイムライン作成を援助する機能だ。ただ、こいつは公開トゥートしか基本載らない。そのため、そこまで活発に活用されている印象はない。それは前述の LTL を意図せず遮ってしまうという側面によるところもあると思っている。多分これはそれほど間違った観察ではなくて、Fedibird では実は LTL を廃止し、公開タイムラインは基本ハッシュタグタイムラインで構築する運用にしているようだ。これは面白いし、向かうべき方向性に思える。つまり、ローカルでの会話をしたかったらインスタンス名つけたハッシュタグをつければいいし、そういう補助をするような UI を持ってもいいだろう。今の LTL の仕組みは、ローカルでの会話から抜け出して別の会話、それも連合全体でテーマに絞った会話をしたくなるみたいな状況には対応できない。しかし、全てハッシュタグ運用にすれば、またそれ用のハッシュタグを持ってくればいいわけだ。実際、Twitter の実況タグなどはそういう使い方がされてるだろう。公開で緩い連帯に基づくグループ会話にハッシュタグは活用でき、好きなタイミングで閉じたり再開でき、また参加をしたりやめたりをできる。さらには、同時に複数のタイムラインで会話が実現できるというのは個人的には割と欲しい機能だ。このような世界は、Fedibird で既に実現されてるらしいし、Misskey でもそれ用の機能があると聞いている。現状僕に対してこれを阻んでいるものは Vivaldi Social の LTL だけなので、ちょっとそういう世界に行ってみたくて近々引っ越しを画策している。個人で運用する Mastodon インスタンス、またはその他のサーバにするか、Fedibird などに行くかは決めてないが、多分近々どっちかに移るかもという感じ。</p>
<p>ここまでが、今の所の僕の Mastodon 体験記ということになる。</p>
</div>
<div class="section" id="mastodon-fediverse">
<h2>Mastodon、あるいは Fediverse の魅力<a class="headerlink" href="#mastodon-fediverse" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Mastodon には商用サービスにも負けない機能、他のサービス以上に魅力のある機能、他のサービスにはない問題点があることがこれまでの体験記を通してなんとなく分かってもらえただろうか? ここではさらに Mastodon の魅力を整理して、言語化してみたいと思う。</p>
<p>一つ断っておくと、これは個人的な価値観による考察で普遍的には通じない、つまり今この記事を読んでいるあなたに通用する考察ではないかもしれない。また、Twitter より Mastodon の方が優れているという話でもない。単に僕が Mastodon について魅力に感じている点をピックアップして紹介しているだけで、Mastodon にはもちろん改善した方がいいと感じる点もある。これは後述する。また、将来に渡って通用する話でもないかもしれない。僕はまだ Fediverse に所属して一ヶ月経っていないため、かなり浅い考察になっている部分はあるだろう。それは踏まえて読んでもらえると良いだろう。</p>
<p>実は僕はここ数年ほど Twitter はあまり呟かなくなっていた。これは僕自身あまり呟くことがない、あるいはその時間がないのだろうと思っていた。ところが、Mastodon を始めてみてこの考えは変わった。どうやら、Twitter は僕にとって呟くことに魅力がなくなってしまったサービスだったようだ。正直この理由はあまりうまく言語化できない。というのは、この原因が自分でもあまりよく分かってないからだ。ただ、いくつか思い当たることはある。まず、Mastodon は明らかに Twitter より安心して呟くことに関して的確な支援が多い:</p>
<dl class="docutils">
<dt>投稿の公開範囲指定機能</dt>
<dd>これは先の体験記で話したとおりで、Twitter にも似たような機能はできたが、微妙に使いにくい。</dd>
<dt>投稿の自動削除機能・インデックス拒否機能</dt>
<dd>これは僕は使ってないが、これがあると安心して投稿できるという人はちらほら見る。まあ、自分がなんも考えずに呟いた投稿が、永遠にインターネットに残り続ける可能性があるというのは結構恐怖という気持ちはわかる。</dd>
<dt>投稿警告機能</dt>
<dd>投稿に関してデフォルトでは警告文のみを出して、投稿全体はボタンを押さないと見れないようにする機能。これによりネタバレ投稿や、他人から見て不快に感じる可能性のある投稿にワンクッションいれることができるようになる。これも、安心して投稿できる範囲を増やすという意味で魅力的な機能だ。</dd>
<dt>投稿文字数制限の大幅な引き上げ</dt>
<dd>Twitter は最近投稿文字数上限を 280 文字に引き上げたらしいが、Mastodon は 500 文字が普通だ。これにより詳細な説明が必要な投稿を気にせずできる。さらに、各クライアントには長文トゥートの折りたたみ機能なども提供されていて、長文投稿による迷惑もあまり考えなくて良い。</dd>
</dl>
<p>基本的にユーザの価値観というのは個々で違うわけだが、そのそれぞれの価値観の反映が、Twitter のような集権的サービスよりも、Fediverse では個々のソフトウェアへの反映となって形に出る幅が広いと感じる。これらの機能は Mastodon が当時から持っていたわけではなく、発展的に採用していったもので、また他のソフトウェアからの影響も多大に受けていると思われる。つまり個々の発展性による多様な価値観の受け入れと、それに対する機能開発の迅速さというのが、個人的な Fediverse の大きな魅力だ。</p>
<p>ただ、これらの支援もさることながら、Twitter の「おすすめ」タブ機能がないというのもどうやら Mastodon で僕がよく呟くようになった要因のようだ。これは Twitter にいた頃には全く意識したことがなかったのだが、Twitter のおすすめは閲覧材料としては優れているのだが、コミュニケーションネットワーク支援としてはかなり悪いアイデアであるようだ。というのは、おすすめにはフォロワーよりも今話題の人や広告、過去のツイートなど、かなり今の自分とかけ離れたものが流れてくることが多く、基本コミュニケーションが成り立たないものが多い。そうなると、自分のツイートへの反応なども迷子になりがちで、また自分の相手への反応も相手がおすすめタブを見ていると伝わらないといったことが起きやすく、反応がいいねとリツイートだけでしか推しはかれなくなる。Twitter を SNS としてみた時、この機能はコミュニケーションを阻害するように働くので、結果的に大きく SNS の魅力を削ぐことになる。逆に言えば、おすすめ機能がない Mastodon はほとんどの人が HTL を見に行くわけで、少なくともそのような阻害要因が一つ除かれていることになる。そうなると、Twitter より SNS としては魅力のあるプラットフォームになるのだ。これはどっちかというと Twitter が下手を打っているという話な気がするが、まあ Twitter と比較した Mastodon の魅力と言っていいだろう。実際僕は Twitter から Mastodon に移ってからかなり投稿数が増え、これが定着の一つの要因となっている。</p>
<p>もう一つ、これも Twitter にいた頃は考えもしなかったのだが、Twitter が人間工学的に下手を打ってそうな部分がある。それはタイムラインの密度だ。体験記の初動で、Twitter のタイムラインに寂しさを覚えたというのが、僕が Mastodon への移行をする直接の動機となったという話をした。実はこれは、少し研究してみて、どうやらタイムラインで一度に見れる投稿が少なく、特に自分に関係がある投稿が少ないことが関係していることが分かってきた。Twitter の公式 Web は結構でかい OGP 表示や、画像・動画表示を愚直に行うし、広告の表示もタイムラインに行う。これはもう一つの公式 Web UI の Tweetdeck では少し緩和されてるもののやはり同じ傾向にあり、あまりカスタマイズもできない。そうなると自然、画像・動画投稿や、リンク投稿が増えると一度に表示される投稿は少なくなる。どうやらこれが寂しさを感じる原因となっているらしい。特に、あまり意味のないヘッダ画像を OGP に据えるサイトが多い中、そういうサイトのリンク投稿が結構多い時にそれをそのまま表示してしまうと、かなりタイムラインを空虚にさせる原因となるようだ。これは Mastodon でも解決されてるというわけではないのだが、TheDesk を使うことで僕は割と解決した。TheDesk の長文投稿折りたたみ機能と、画像のクロップ機能を使うことで、Mastodon 側のタイムラインはかなり密度を保てており、これは結構僕的には定着率向上に貢献している。また、TheDesk が URL の概要表示をそこまで積極的にしないというのも大きい。これは、エンゲージメント減少には繋がっているかもしれないので、ビジネスとの兼ね合いで見たときには微妙かもしれない。また、これは個人的な価値観によるところも大きいのかもしれない。だが、少なくとも僕にとってはかなり致命的だったわけだ。</p>
<p>また、Fediverse 全体の魅力として、やはり運用者が個々におり、ソフトウェアも多数あり、選択肢の幅が広いというのも一つの魅力だ。特に Mastodon には引っ越し機能があり、多少のリスクはあるが、ノードを移動して別のとこにいく支援を受け入れられるという点も良い。これはいざという時の保険にもなるし、発展性の一つの支えにもなっていると思う。引っ越し機能を使っているユーザは結構多いし、気軽に使える。こうして、それぞれのノードの文化を取り入れつつ、自身の今の状況にあった場所をその時々で見つけられるというのは Fediverse ならではの魅力だと思う。</p>
</div>
<div class="section" id="auto-id-5">
<h2>Mastodon、あるいは Fediverse の課題<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>もちろん Fediverse には課題も多い。それについても言語化しておこう。</p>
<p>もう一回念のため断っておくと、これは個人的な価値観による考察で普遍的には通じない、つまり今この記事を読んでいるあなたに通用する考察ではないかもしれない。また、 Mastodon が向くべき方向性を間違っているという話でもない。単に僕が今の Mastodon について感じる不満を書いているだけ。また、将来に渡って通用する話でもないかもしれない。僕はまだ Fediverse に所属して一ヶ月経っていないため、かなり浅い考察になっている部分はあるだろう。それは踏まえて読んでもらえると良いだろう。</p>
<p>まずこれは多分異論が出ないと思うのだが、今の Fediverse は検索性がかなり弱い。これは Twitter での経験があるというのも大きいだろうが、辿り着きたいと思ったタイムラインやトゥート、ユーザにたどり着けることがあまり多くない。そしてこれはかなり需要があるだろう。では、なぜ実現できないのか? 技術的な問題というのも確かにあるだろうが、個人的にはやはり資本力の差が大きいと感じる。多分検索機能は大体やればできる。要は Fediverse のトゥートに限った検索エンジンを作ってしまえばいいだけで、課題も多いだろうが、解決できないというほどでもないと思っている。にも関わらず、そのような機能が現れないのは、一つには検索エンジンは技術的にはそう難しくないのだが、運用コストがバカにならないという問題があるからだと思っている。体験記でも述べたのだが、Fediverse は金で殴れない分それがもろに効いてくる部分で結構脆弱である。これを技術だけで解決できればかっこいいのだろうが、なかなか難しいところだろう。</p>
<p>検索が弱いというのもそうだが、Fediverse は全体的に繋がりを作った後の支援機能は多いのだが、繋がりを作る部分についての機能が薄いと感じる。おすすめのユーザやトレンドはそこまで機能していないと思うし、検索性も薄く、さらにはユーザがそれぞれのリモートサーバに散らばっていることを考えると、Twitter より的確にユーザやクラスタを探すのはかなり難易度が高いと思う。少なくとも僕は結構苦労している。これは、繋がりを増やしたいという動機を持っている現ユーザが少ないのもありそうだが、新規参入者では結構問題になるだろうなとは思っている。こういう新規参入支援が薄い部分は、やっぱビジネスでやってる商用サービスと違うところだなとは思う。</p>
<p>さて、もう一つ、おそらく結構な人数の間で Fediverse が選ばれない、あるいは離脱者が多い理由に人口があると思う。これは、まあ解決すべきかと解決できるのかという問題もあると思うが、ただここで言っているのは単純な人口の話というより、網羅率というか、今の Fediverse には参入できない人が多く、また今の Fediverse の正確な人口に比して、それを感じられる機会が少ないという感じの話だ。</p>
<p>まず、現在の Fediverse はかなり参入障壁が高いと思っている。幾つか理由はあるがやはり分散性がかなり効いていると思う。分散的であるということは、それだけ扱う対象が増えるという話で、これは検索性の阻害にも繋がっているわけだが、そもそも対象が一つしかないものより対象が複数のものの方が学習コストは高くなるという問題もある。そうなると自然、学習コストが低いものよりもサービス開始につながらないユーザは増えるわけだし、サービス開始ができてもその後の体験の向上に繋がるまで時間がかかるだろう。また、知らなければいけないこともかなり増える。例えば、この記事はかなり技術的知識を前提に書かれているわけだが、世間のほとんどの人にとってちんぷんかんぷんな説明も多いだろう。Fediverse において、そういう技術的知識込みでの説明を入れないと物事が正確に説明できない場面が多いと感じる。もちろん、それは時間をかけて説明を噛み砕けば解決できるのだろうが、そこまでのコストを払って啓蒙を行う人は少ないだろう。また、啓蒙を行ったとしてそこに辿り着く導線を作れるかというのも問題になる。Mastodon の UI もところどころ結構リテラシーの高さを要求してくる部分があり、割と足切りラインはありそうと感じる。まあ、その分治安が保たれるという見方はできるかもしれないが。</p>
<p>また、検索性がないこともあって、どの人がネットワーク内にいるか把握しづらく、実際より人口がいない印象を受けやすいという面もあると思う。繋がりを作るのにも割かしコストがかかるので、そのまま馴染めず、離脱する人が多いのだろう。この辺の導入支援が少ないのは、ビジネスでやってないサービスの共通点で弱いところではあると思っていて、まあそれはそもそもそこに動機がないからだが、だからこそ成長が遅いという側面はありそうだ。基本 SNS の魅力として人口はかなり大きいと思う。個人的には、そこに動機がないことが今回分かったのだが、大多数の人にとっては友達が使ってるから繋がりを持つために自分も使ってみるというのが動機としては大きいだろう。僕としても、もし人口が多く Mastodon 並に魅力的な機能があれば、多分そっちに流れるだろう。逆に言えば人口は Fediverse の生命線になり得るということで、課題の一つに挙げておいてもいいんじゃないかと思う。</p>
<p>さて、最後が Mastodon のキャッチである「売り物ではないソーシャルネットワークサービス」というものに対してだ。正直僕が最近まで Mastodon を敬遠していたのはこのキャッチによるところが大きいと思う。これはおそらく僕の価値観によるところが大きいのだろうが、ビジネスで運用されていないサービスほど胡散臭いものはないというのが僕は思っていて、その価値観で言うと Mastodon はそもそも思想からして色々反しているわけだ。まず、どこの国の法でも大体そうなのだが、非営利で運用しているサービスというのはある程度免責される部分が出てくる。逆に営利企業には様々な制約が法律レベルでかかり、まともな企業であればそれを守らざるを得ないし、もし守ってないことが明るみに出た場合は法に基づいた民事係争手続きによるしかるべき処置や補填を求めることなどもできる。つまり何が言いたいかというと、一般的に非営利より営利の方がある程度セキュリティレベルや財務の健全性などが保証されている場合が多く、また利用者の権益も法律によって保護される場合が多いということだ。これは一般のイメージとは真逆かもしれないが、非営利というのは口で割と出まかせを言って何とかできる範囲が大きく、実際それは度々問題になっている。ビジネスでやってるところはそれなりにセキュリティや財務健全性にも力を入れている。それは入れざるを得ないからなわけだが、非営利ではそこがおざなりになりがちだ。ま、もちろんビジネスでやってるから安全とか、ビジネスでやってないからやばいという話ではないが、一般論として個人的にはビジネスでやってもらった方が信頼が持てる。そこは課題なのか?と思う人も多いだろう。ただ、Fediverse 全体として商用サービス化への忌避があると思っていて、それは逆に安定的で信頼のあるプラットフォームを築くための障害になるだろうなという感じだ。実際、今の Fediverse の管理者には、「自分は苦労して何のメリットもない管理者を買って出ているのに、なぜ更なる苦労を強いられなければいけないんだ」とか「メリットを自分で作ってもいいだろう」という声を持つ人もたまにいることを観測している。これは真っ当な感想であり、僕は1ユーザにしか甘んじていないためあまり強く言える立場ではないのだが、こういう動機からえてして色々な線を越える行動に出る個人や団体は多いというのが現実だ。これは善意と努力で行われている場合、ふとした弾みにより暴発しやすく、法的責任もない場合が多いのでそのまま有耶無耶になりがちだ。このようなことが起こりやすい土壌は、サービスとしてあまり健全ではなく、世間一般にあまり受け入れられてほしくはないと僕は思っている。世間一般に受け入れられるには、ちゃんと信頼性のあるサービス運用と健全な財務に力をいれて、正当な手続きを用意する手間を惜しまないプラットフォームであるべきで、そういうプラットフォームであるには専任で時間を使う人たちが必要で、専任で時間を使うには金と保証が必要だ。これは善意と献身によるサービス運営では、あまり実現できないだろう。もし、Fediverse が世間一般に受け入れられることを目指しているなら、個人的にはこの課題は解決してほしいと思う。</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、Mastodon を始めてからの振り返りと、魅力と課題についての紹介だった。ま、とりあえず Mastodon は楽しい。Misskey も楽しそう。</p>
<p>Twitter は多分アカウントはそのまま当分なんかあるまで残すけど、呟くことはないかなという感じ。Fediverse 崩壊しても Twitter 以外に流れそう。大したこと呟いてないが、興味あったらフォローしてくれ (<a class="reference external" href="https://social.vivaldi.net/@mizunashi">https://social.vivaldi.net/@mizunashi</a>)、よろしく。では、今回これで。</p>
<table class="docutils footnote" frame="void" id="mastodon-doc-privacy" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[1]</a></td><td><a class="reference external" href="https://docs.joinmastodon.org/ja/user/posting/#privacy">https://docs.joinmastodon.org/ja/user/posting/#privacy</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="pawoo-domain-block" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[2]</a></td><td><a class="reference external" href="https://togetter.com/li/1101173">https://togetter.com/li/1101173</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/02/mastodon-experience.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/02/mastodon-experience.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>SecureRandom.getInstanceStrong を気軽に使ってはいけない2023-02-05T04:16:35+09:002023-02-05T04:16:35+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-02-05:/blog/posts/2023/02/use-securerandom-getinstancestrong-carefully/<p>何番煎じか分からないが、個人的に詰まったので備忘録。JDK には、暗号用の乱数生成器 <a class="reference external" href="https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/security/SecureRandom.html">SecureRandom</a> クラスが用意されている。そし …</p><p>何番煎じか分からないが、個人的に詰まったので備忘録。JDK には、暗号用の乱数生成器 <a class="reference external" href="https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/security/SecureRandom.html">SecureRandom</a> クラスが用意されている。そして、このクラスには、 <a class="reference external" href="https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/security/SecureRandom.html#getInstanceStrong()">getInstanceStrong</a> というメソッドが用意されている。この名前はいかにも強そうで、基本的にはこのメソッドを使っていれば安全そうに見える。ところが、このメソッドは何も考えずに使うと思わぬ落とし穴にハマることになる。今回はその話をする。</p>
<div class="section" id="auto-id-1">
<h2>突然フリーズするサーバ<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>アリスはボブに頼まれ、単純なデータベースへの読み書きを担当する API サーバを作ることになった。読み書きするデータは機密性の高いもので、万が一にも漏洩するのは良くないし、生データに触れるのも制限された人のみにすべきで、それはアリスに対しても開示できないものなので、データベースに保存するデータは全てサーバ側で書き込み側から鍵を受け取って暗号化してから保存することになった。アリスは普段使い慣れている Java でサーバを書くことにした。開発は順調で、手元でアリスは万全のテストを行い、自信を持ってボブに完成したサーバプログラムを渡した。</p>
<p>ところがその数日後、ボブからクレームが来ることになる。君からもらったプログラムはまるで使いものにならない、サーバはある程度リクエストを受け付けるとフリーズしてしまうというのだ。それも、秒間数千リクエストとかではない。ほんの数リクエスト程でというのだ。それぐらいの状況ならアリスはテスト済みだ。どうせサーバの起動環境の問題だろうと思いつつ、ボブに請われて原因調査のためインスタンスに潜る。すると確かに、アリスが作ったサーバはほんの数リクエストでレスポンスを返さなくなってしまうようだった。ただ、データベースへの接続が止まっている雰囲気でもない。不思議に思いながら、アリスはひとまずスレッドダンプを取ってみることにした。 <tt class="docutils literal">jps</tt> でサーバのプロセス ID を調べ、 <tt class="docutils literal">jstack</tt> でスレッドダンプを表示してみたところ、何やら不思議なダンプ情報が出力された:</p>
<pre class="literal-block">
$ jstack 9
...
"Thread-0" #13 prio=5 os_prio=0 cpu=23.44ms elapsed=12.94s tid=0x0000ffff88172de0 nid=0x1c runnable [0x0000ffff5cdec000]
java.lang.Thread.State: RUNNABLE
at java.io.FileInputStream.readBytes(java.base@17.0.6/Native Method)
at java.io.FileInputStream.read(java.base@17.0.6/FileInputStream.java:276)
at java.io.FilterInputStream.read(java.base@17.0.6/FilterInputStream.java:132)
at sun.security.provider.NativePRNG$RandomIO.readFully(java.base@17.0.6/NativePRNG.java:425)
at sun.security.provider.NativePRNG$RandomIO.getMixRandom(java.base@17.0.6/NativePRNG.java:405)
- locked <0x000000008cf91998> (a java.lang.Object)
at sun.security.provider.NativePRNG$RandomIO.implNextBytes(java.base@17.0.6/NativePRNG.java:537)
at sun.security.provider.NativePRNG$Blocking.engineNextBytes(java.base@17.0.6/NativePRNG.java:269)
at java.security.SecureRandom.nextBytes(java.base@17.0.6/SecureRandom.java:758)
at DataCryptor.encrypt(DataCryptor.java:66)
at ApiService.registerData(ApiService.java:15)
at Server.run(Server.java:10)
at java.lang.Thread.run(java.base@17.0.6/Thread.java:833)
...
</pre>
<p>どうやら、 <tt class="docutils literal">SecureRandom.nextBytes</tt> の呼び出しが止まっているようだ。該当部分のコードは以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">...</span>
<span class="kd">public</span><span class="w"> </span><span class="kd">class</span> <span class="nc">DataCryptor</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">ThreadLocal</span><span class="o"><</span><span class="n">Cipher</span><span class="o">></span><span class="w"> </span><span class="n">cipherThreadLocal</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ThreadLocal</span><span class="o"><></span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">protected</span><span class="w"> </span><span class="n">Cipher</span><span class="w"> </span><span class="nf">initialValue</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">Cipher</span><span class="p">.</span><span class="na">getInstance</span><span class="p">(</span><span class="n">CIPHER_ALGORITHM</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">NoSuchAlgorithmException</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">NoSuchPaddingException</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">"unreachable: expect AES/GCM/NoPadding support"</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">ThreadLocal</span><span class="o"><</span><span class="kt">byte</span><span class="o">[]></span><span class="w"> </span><span class="n">gcmNonceBytesThreadLocal</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ThreadLocal</span><span class="o"><></span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">protected</span><span class="w"> </span><span class="kt">byte</span><span class="o">[]</span><span class="w"> </span><span class="nf">initialValue</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="kt">byte</span><span class="o">[</span><span class="mi">12</span><span class="o">]</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">};</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">SecretKeySpec</span><span class="w"> </span><span class="n">keySpec</span><span class="p">;</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">SecureRandom</span><span class="w"> </span><span class="n">random</span><span class="p">;</span>
<span class="w"> </span><span class="n">DataCryptor</span><span class="p">(</span><span class="kt">byte</span><span class="o">[]</span><span class="w"> </span><span class="n">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">assert</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="na">length</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">KEY_BIT_LENGTH</span><span class="p">;</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">keySpec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">SecretKeySpec</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">KEY_ALGORITHM</span><span class="p">);</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">random</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SecureRandom</span><span class="p">.</span><span class="na">getInstanceStrong</span><span class="p">();</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">NoSuchAlgorithmException</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">"unreachable: expect SecureRandom strong algorithm support"</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">public</span><span class="w"> </span><span class="kt">byte</span><span class="o">[]</span><span class="w"> </span><span class="nf">encrypt</span><span class="p">(</span><span class="kt">byte</span><span class="o">[]</span><span class="w"> </span><span class="n">plain</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="n">Cipher</span><span class="w"> </span><span class="n">cipher</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cipherThreadLocal</span><span class="p">.</span><span class="na">get</span><span class="p">();</span>
<span class="w"> </span><span class="kd">final</span><span class="w"> </span><span class="kt">byte</span><span class="o">[]</span><span class="w"> </span><span class="n">nonce</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">gcmNonceBytesThreadLocal</span><span class="p">.</span><span class="na">get</span><span class="p">();</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">random</span><span class="p">.</span><span class="na">nextBytes</span><span class="p">(</span><span class="n">nonce</span><span class="p">);</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">...</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>これの <tt class="docutils literal">encrypt</tt> メソッド3行目が該当部分のようだった。なんの変哲もない <tt class="docutils literal">SecureRandom.nextBytes</tt> の呼び出しに見える。一体全体なぜこんなところでフリーズするんだろう。もう一度ダンプをよく見てみよう:</p>
<pre class="literal-block">
at sun.security.provider.NativePRNG$RandomIO.implNextBytes(java.base@17.0.6/NativePRNG.java:537)
at sun.security.provider.NativePRNG$Blocking.engineNextBytes(java.base@17.0.6/NativePRNG.java:269)
at java.security.SecureRandom.nextBytes(java.base@17.0.6/SecureRandom.java:758)
</pre>
<p>どうやら、 <tt class="docutils literal">SecureRandom.nextBytes</tt> の呼び出しは実際には <tt class="docutils literal">NativePRNG.Blocking.engineNextBytes</tt> と呼び出しになるようだ。名前に <tt class="docutils literal">Blocking</tt> という文字が入っているのが気になるところだ。さて、そもそもこの記事はタイトル落ちなのだが、実際の問題の箇所は以下の部分だ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">DataCryptor</span><span class="p">(</span><span class="kt">byte</span><span class="o">[]</span><span class="w"> </span><span class="n">key</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">assert</span><span class="w"> </span><span class="n">key</span><span class="p">.</span><span class="na">length</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">KEY_BIT_LENGTH</span><span class="p">;</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">keySpec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">SecretKeySpec</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">KEY_ALGORITHM</span><span class="p">);</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="na">random</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SecureRandom</span><span class="p">.</span><span class="na">getInstanceStrong</span><span class="p">();</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="n">NoSuchAlgorithmException</span><span class="w"> </span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">RuntimeException</span><span class="p">(</span><span class="s">"unreachable: expect SecureRandom strong algorithm support"</span><span class="p">,</span><span class="w"> </span><span class="n">e</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>つまり、 <tt class="docutils literal">SecureRandom</tt> のインスタンスを作成してる部分、つまり <tt class="docutils literal">this.random = SecureRandom.getInstanceStrong()</tt> の部分だ。ただ、この原因の説明には少し時間が必要だ。では、なぜこのような現象が起こるのか見ていこう。</p>
</div>
<div class="section" id="auto-id-2">
<h2>SecureRandom.getInstanceStrong<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>アリスがつまづいたポイントを理解するには、まず <tt class="docutils literal">SecureRandom.getInstanceStrong</tt> メソッドがどういう動作をするかを理解しなければいけないだろう。<a class="reference external" href="https://docs.oracle.com/javase/jp/19/docs/api/java.base/java/security/SecureRandom.html#getInstanceStrong()">Oracle の JavaSE 19 向けのドキュメント</a> には、以下のような記述がある:</p>
<blockquote>
<p>securerandom.strongAlgorithmsSecurityプロパティで指定されたアルゴリズムまたはプロバイダを使用して選択されたSecureRandomオブジェクトを返します。</p>
<p>RSA公開/非公開キーのような付加価値の高い永続的な秘密情報を作成する場合など、状況によっては強力な乱数値が必要になります。 アプリケーションが適切で強力なSecureRandom実装を選択できるようにするため、Javaディストリビューションでは、securerandom.strongAlgorithmsセキュリティ・プロパティに既知の強力なSecureRandom実装のリストが含まれています。</p>
</blockquote>
<p>つまり、 <tt class="docutils literal">SecureRandom.getInstanceStrong</tt> メソッドが返すインスタンスはSecurityプロパティの <tt class="docutils literal">securerandom.strongAlgorithms</tt> の値によって変わり、そのプロパティも Java ディストリビューションによって変わるというわけだ。Securityプロパティというのは、<a class="reference external" href="https://docs.oracle.com/javase/jp/19/docs/api/java.base/java/security/Security.html#getProperty(java.lang.String)">Security.getProperty</a> で取得できる値のこと。<a class="reference external" href="https://docs.oracle.com/javase/jp/19/docs/api/java.base/java/security/Security.html">java.security.Security のドキュメント</a> によると</p>
<blockquote>
セキュリティ・プロパティのデフォルト値は、実装固有のロケーション(通常はJavaインストール・ディレクトリのプロパティ・ファイルconf/security/java.security)から読み取られます。</blockquote>
<p>とのことで、<a class="reference external" href="https://github.com/openjdk/jdk/blob/jdk-19%2B36/src/java.base/share/conf/security/java.security#L168-L173">OpenJDK の定義</a> では、以下のようになっている:</p>
<dl class="docutils">
<dt>Windows 以外</dt>
<dd>NativePRNGBlocking:SUN,DRBG:SUN</dd>
<dt>Windows</dt>
<dd>Windows-PRNG:SunMSCAPI,DRBG:SUN</dd>
</dl>
<p>この形式についての説明はちょっと見つけられなかったが、<a class="reference external" href="https://github.com/openjdk/jdk/blob/jdk-19%2B36/src/java.base/share/classes/java/security/SecureRandom.java#L933-L977">OpenJDK の実装</a> を読む限り、 <tt class="docutils literal"><span class="pre">Algorithm1:Provider1,Algorithm2:Provider2,...</span></tt> という形式のようだ。優先順位は左からのようだ。つまり、Windows 以外の環境では NativePRNGBlocking というアルゴリズムが SUN プロバイダにあればそれが使われる。Windows では Windows-PRNG というアルゴリズムが SunMSCAPI プロバイダにあればそれが使われる。そして、それらが無ければ DRBG というアルゴリズムが SUN プロバイダにあればそれが使われるということになる。</p>
<p>アリスの手元は macOS/AArch64、サーバが実際に動いた環境は Linux/x64 の環境だった。そしてどちらの環境も SUN プロバイダで NativePRNGBlocking アルゴリズムが提供されていた。つまり、どちらにしても <tt class="docutils literal">SecureRandom.getInstanceStrong()</tt> は <tt class="docutils literal"><span class="pre">SecureRandom.getInstance("NativePRNGBlocking",</span> "SUN")</tt> と同じということで、アルゴリズムの違いによって動作に違いが生まれていたわけではない。問題なのはこの NativePRNGBlocking アルゴリズム自体の動作というわけだ。</p>
</div>
<div class="section" id="auto-id-4">
<h2>SecureRandom のアルゴリズム<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、NativePRNGBlocking の詳細に入る前に、SecureRandomの実装アルゴリズムの概要について少し見ておこう。アルゴリズムの一覧は、 <a class="reference external" href="https://docs.oracle.com/javase/jp/19/docs/specs/security/standard-names.html#securerandom-number-generation-algorithms">Javaセキュリティ標準アルゴリズム名</a> 及び <a class="reference external" href="https://docs.oracle.com/javase/jp/19/security/oracle-providers.html#GUID-9DC4ADD5-6D01-4B2E-9E85-B88E3BEE7453">Java SE セキュリティ開発者ガイド</a> で説明されている。それぞれまとめると</p>
<table border="1" class="docutils">
<colgroup>
<col width="21%"/>
<col width="11%"/>
<col width="68%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">アルゴリズム</th>
<th class="head">プロバイダ</th>
<th class="head">概要</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>NativePRNG</td>
<td>SUN</td>
<td>基盤となるネイティブOSから乱数を取得する。 乱数生成のブロック性について
は何も表明されない。基本実装は、<tt class="docutils literal">nextBytes</tt> では <tt class="docutils literal">/dev/urandom</tt> 、
<tt class="docutils literal">generateSeed</tt> では <tt class="docutils literal">/dev/random</tt> が使用される。</td>
</tr>
<tr><td>NativePRNGBlocking</td>
<td>SUN</td>
<td>基盤となるネイティブOSから乱数を取得し、必要に応じてブロック化する。基本
実装は、<tt class="docutils literal">nextBytes</tt> 、 <tt class="docutils literal">generateSeed</tt> で <tt class="docutils literal">/dev/random</tt> が使用され
る。</td>
</tr>
<tr><td>NativePRNGNonBlocking</td>
<td>SUN</td>
<td>基盤となるネイティブOSから乱数を取得するが、アプリケーションの速度低下を
避けるためブロックしない。基本実装は、<tt class="docutils literal">nextBytes</tt> 、 <tt class="docutils literal">generateSeed</tt>
で <tt class="docutils literal">/dev/urandom</tt> が使用される。</td>
</tr>
<tr><td>PKCS11</td>
<td>SunPKCS11</td>
<td>基礎となるインストール済および構成済のPKCS #11ライブラリから乱数を取得す
る。</td>
</tr>
<tr><td>DRBG</td>
<td>SUN</td>
<td>NIST SP 800-90Ar1 で定義されている DRBG メカニズムを使用するアルゴリズ
ムを使用する。</td>
</tr>
<tr><td>SHA1PRNG</td>
<td>SUN</td>
<td>各操作につき値が1増加する64ビット・カウンタを使って鎖状につながった真に
ランダムなシード値から、SHA-1ハッシュを計算する疑似乱数生成アルゴリズム
を使用する。初期シードは、現在、システム属性とjava.securityエントロピー
収集デバイスの組合せによって決定される。</td>
</tr>
<tr><td>Windows-PRNG</td>
<td>SunMSCAPI</td>
<td>基盤となるWindows OSから乱数を取得する。</td>
</tr>
</tbody>
</table>
<p>ここまでで何が問題か分かった人は多いと思うが、 <tt class="docutils literal">NativePRNGBlocking</tt> の必要に応じてブロックするというところ、特に <tt class="docutils literal">/dev/random</tt> が通常使われるというところが問題になる。簡単に言えば <tt class="docutils literal">/dev/random</tt> つまり <tt class="docutils literal">NativePRNGBlocking</tt> の取得元は真の乱数のみを生成するようになっており、十分な乱数性が保証されていない状態では乱数性が保証されるまでブロックを行うのだ。Linux での乱数生成についてはこの後触れるが、基本的に OS は普段からハードウェア割り込みなどタイミングが予測不能のイベントを観測するなどして環境ノイズから乱数源を確保している。そして、 <tt class="docutils literal">/dev/random</tt> が参照されるとその乱数源に溜め込まれたノイズから乱数を生成する。ただ、ノイズは使ったら再利用できないので、乱数生成ごとに使えるノイズは減っていくわけで、無限にノイズを貯めるのも難しいため枯渇する状況は発生してしまう。そのような場合に <tt class="docutils literal">/dev/random</tt> はノイズがまた必要な分貯まるまで乱数生成をブロックするというわけだ。環境ノイズは基本的に稼働している外部デバイスがある程度多くないとあまり貯まらない。特に、サーバ用途で普段外部要因があまり関わらないような放置された環境だと、ノイズ元があまりなく、十分な乱数源が確保されるまで時間がかかることが多い。例え、乱数生成がブロックされなかったとしても、本当に真の乱数が必要な他のプログラムに影響を与えるということにもなりかねない。ここから、サーバなどで <tt class="docutils literal">/dev/random</tt>、つまり <tt class="docutils literal">NativePRNGBlocking</tt> アルゴリズムを使う場合は注意が必要だ。</p>
<p>さて、今回のアリスのサーバは意図して <tt class="docutils literal">/dev/random</tt> を使ったわけではないが、 <tt class="docutils literal">SecureRandom.getInstanceStrong()</tt> の中身が実際には <tt class="docutils literal">NativePRNGBlocking</tt> だったため、結果的にノイズを消費しつつノイズがなくなったら貯まるまでブロックするという動作を起こすコードになっていたというわけだ。手元では、普段からキーボード入力やマウス入力、音声デバイスの使用など様々なノイズ源があるため、あまり <tt class="docutils literal">/dev/random</tt> のブロックという事態までには至りにくかったが、ノイズが枯渇しがちな実際の環境ではデータ暗号化毎にノイズを消耗してしまうため、ノイズの枯渇という事態に陥りサーバがフリーズするという事態になったわけだ。アリスは結局、 <tt class="docutils literal">SecureRandom.getInstanceStrong()</tt> を使う代わりにブロックしないことが保証されている <tt class="docutils literal"><span class="pre">SecureRandom.getInstance("NativePRNGNonBlocking")</span></tt> を使うことにした。その後サーバのフリーズという事態は起きず、ボブの事業も成長していきましたとさ。めでたしめでたし。</p>
<p>ところで、アリスはブロックしないことを理由に <tt class="docutils literal">NativePRNGNonBlocking</tt> を使うことにしたわけだが、この選択は正しいのだろうか?そもそもなぜ <tt class="docutils literal">SecureRandom.getInstanceStrong</tt> はデフォルトでブロックするような実装になるのだろうか? 先ほど少し触れたが、基本的に <tt class="docutils literal">NativePRNGBlocking</tt> がブロックを起こすのは結果的な話で、目的としては真の乱数のみを使えるようにすることにある。では、 <tt class="docutils literal">NativePRNGNonBlocking</tt>、つまり <tt class="docutils literal">/dev/urandom</tt> とはどういう実装になっているのかという話なのだが、こちらは暗号的な強度をある程度落とす代わりにブロックしないようなアルゴリズムになっているのだ。具体的には、初期シードはノイズ源から生成しそこから疑似乱数を生成するような生成器を用意しておき、ノイズ元が不足している場合はそちらの生成器から乱数を生成するようになっているのだ。そんなことをして安全なんだろうか? そこら辺の詳細は後で説明するが、使用上の注意点は確かに幾つかある。ただ、基本的に <tt class="docutils literal">/dev/urandom</tt> も速度より安全性を重視した実装になっており、注意点が守られるなら長期に何度も再利用されるような乱数列を生成するのでない限りは目的に沿うぐらいの強度は得られるだろう。</p>
<p>実際、 <tt class="docutils literal">SecureRandom</tt> のコンストラクタでインスタンスを作った場合、標準的には <tt class="docutils literal">NativePRNG</tt> が実装として使われることになるが、この際 <tt class="docutils literal">nextBytes</tt> で使われるのも <tt class="docutils literal">/dev/urandom</tt> になる。基本的には、 <tt class="docutils literal">SecureRandom.getInstanceStrong</tt> を使う場面というのは JavaSE のドキュメントで述べられている通り、付加価値が高く永続性も高いような乱数列の生成、つまり暗号化用の秘密鍵のようなものだ。それ以外についても、性能が許すなら真の乱数源からの生成を行なってもいいだろうが、あまりにノイズを消費しすぎると、他のプログラムにも影響が出かねないし、ノイズの質も落ちやすくなってしまう。そこのトレードオフを考えつつ、使用するべきだろう。なお、 <tt class="docutils literal">SecureRandom</tt> の標準的な実装の優先順位、つまりコンストラクタでインスタンスを作った場合に選ばれるアルゴリズムの優先順位は <a class="reference external" href="https://docs.oracle.com/javase/jp/19/security/oracle-providers.html#GUID-9DC4ADD5-6D01-4B2E-9E85-B88E3BEE7453">セキュリティ開発者ガイド</a> で述べられており、以下のようになっている:</p>
<dl class="docutils">
<dt>Linux</dt>
<dd><ol class="first last arabic simple">
<li>NativePRNG</li>
<li>DRBG</li>
<li>SHA1PRNG</li>
<li>NativePRNGBlocking</li>
<li>NativePRNGNonBlocking</li>
</ol>
</dd>
<dt>macOS</dt>
<dd><ol class="first last arabic simple">
<li>NativePRNG</li>
<li>DRBG</li>
<li>SHA1PRNG</li>
<li>NativePRNGBlocking</li>
<li>NativePRNGNonBlocking</li>
</ol>
</dd>
<dt>Windows</dt>
<dd><ol class="first last arabic simple">
<li>DRBG</li>
<li>SHA1PRNG</li>
<li>Windows-PRNG</li>
</ol>
</dd>
</dl>
<p>なお、Linux、macOS には注記があり、</p>
<blockquote>
java.securityのエントロピー収集デバイスをfile:/dev/urandomまたはfile:/dev/randomに設定すると、SHA1PRNGよりNativePRNGが優先されます。それ以外の場合は、SHA1PRNGが優先されます。</blockquote>
<p>ということのようだ。OpenJDK では基本このプロパティが設定されているようなので、優先順位は基本書いた通りになると思っていいだろう。先ほどのアルゴリズムの解説を合わせると、どのプラットフォームでも優先度が高いものは、シード生成は真の乱数を元に生成、乱数生成はシードを元にした疑似乱数の生成ということになり、 <tt class="docutils literal">/dev/urandom</tt> 相当のものになることが分かる。アリスの場合シード生成には <tt class="docutils literal">SecureRandom</tt> インスタンスを使っていないため、標準基準と同レベルと言えるもので、特に問題ないだろう。</p>
<p>なお余談だが、アリスのスレッドダンプは <a class="reference external" href="https://github.com/mizunashi-mana/securerandom-getinstancestrong-freeze-cfp">https://github.com/mizunashi-mana/securerandom-getinstancestrong-freeze-cfp</a> のリポジトリのコードで再現した。基本的には、 <tt class="docutils literal">/dev/random</tt> をパイプファイルで上書きしておき、 <tt class="docutils literal">/dev/random</tt> のブロックを擬似的に再現している。興味があったら覗いてみてくれ。</p>
</div>
<div class="section" id="os">
<h2>OS の乱数生成<a class="headerlink" href="#os" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、 <tt class="docutils literal">SecureRandom</tt> のインスタンス選びには多少注意が必要なことは分かってきたと思う。最後に、 <tt class="docutils literal">SecureRandom</tt> 標準のアルゴリズムが内部で使用している、 <tt class="docutils literal">/dev/random</tt>、 <tt class="docutils literal">/dev/urandom</tt> についてもう少し中身を詳しく見ておこうと思う。なお、以降の話は Linux カーネルでの話。それ以外は知らん。</p>
<p>Linux の <tt class="docutils literal">/dev/random</tt>、 <tt class="docutils literal">/dev/urandom</tt> の実装は最近結構大きく変わった <a class="footnote-reference" href="#linux-rng-history" id="auto-id-6">[1]</a>。ただまだ変更後のカーネルを使ってるところは少ないだろうと思うので、一応変わる前後について両方見ておこう。混乱を避けるため、変更前のアーキテクチャを Linux-Legacy-RNG、変更後のアーキテクチャを ChaCha20-DRNG と呼ぶことにする。まずは Linux-Legacy-RNG の方から見ていく。さて、今まで <tt class="docutils literal">/dev/random</tt> は OS が集めた環境ノイズを消費しつつ乱数を生成するというぼかした説明をしてきた。正確には、乱数の生成源はいくつか種類があり、その概要は以下のようになっている:</p>
<img alt="Linux-Legacy-RNG の概要図" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/use-securerandom-getinstancestrong-carefully/use-securerandom-getinstancestrong-carefully/linux-rng-overview.png"/>
<p>なお、この図は以下のレポートから拝借した:</p>
<blockquote>
Patrick Lacharme, Andrea Röck, Vincent Strubel, and Marion Videau. 2012. The Linux Pseudorandom Number Generator Revisited. Retrieved from <a class="reference external" href="https://eprint.iacr.org/2012/251.pdf">https://eprint.iacr.org/2012/251.pdf</a></blockquote>
<p>まず、乱数の生成源の乱雑さを表す状態量をエントロピーと呼ぶが、OS はこのエントロピーをエントロピー元、つまりハードウェア割り込みなどの環境ノイズから上手く抽出し、入力プール (input pool) に溜め込んでおく。このエントロピーが高いほど、入力プールは質の良い状態、つまり極めて乱雑になっているということだ。入力プールは実際には、固定サイズのビット列プールで、エントロピー源から得たビット情報を都度混ぜ合わせた乱数列を保持している。ただ、 <tt class="docutils literal">/dev/random</tt>、 <tt class="docutils literal">/dev/urandom</tt> は直接この入力プールからエントロピーを抽出して使うのではなく、一度ビット情報を必要に応じてそれぞれのプールに持ってくる。 <tt class="docutils literal">/dev/random</tt> はブロッキングプールを参照する。ブロッキングプールは自身のエントロピーを監視しつつエントロピーが不足してくると都度入力プールからエントロピーを抽出し、自身の今の情報と混ぜ合わせながらエントロピーを補充、つまり乱雑なビット列を保つ。そして、 <tt class="docutils literal">/dev/random</tt> の参照元にその乱雑なビットを返しつつ参照された分自身へのフィードバックをしつつ、エントロピーの評価を下げていく。 <tt class="docutils literal">/dev/urandom</tt> が参照する非ブロッキングプールも基本的には同じようなことを行うが、エントロピーが入力プールから補充できない場合は補充を諦め、現在のプールの状態のまま乱数列を生成する。まあ、ここら辺の具体的なアルゴリズムは興味があれば実装を読んでみるといいと思うが、実益を兼ねてということであれば、この後紹介する ChaCha20-DRNG の方を参照することをお勧めする。Linux-Legacy-RNG のコードベースはかなり混沌としており、この状況の改善も ChaCha20-DRNG プロジェクトの一つの目的であり、そっちの方が読みやすい。また、今後は ChaCha20-DRNG の方が主流になっていくだろうからだ。</p>
<p>さて、ChaCha20-DRNG では Linux-Legacy-RNG と異なり、ブロッキングプールが実は廃止された。以下がその概要図になる:</p>
<img alt="ChaCha20-DRNG の概要図" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/02/use-securerandom-getinstancestrong-carefully/use-securerandom-getinstancestrong-carefully/chacha20-drng-overview.png"/>
<p>なお、この図は以下のレポートから拝借した:</p>
<blockquote>
<ol class="arabic simple" start="2020">
<li>Documentation and Analysis of the Linux Random Number Generator. Retrieved from <a class="reference external" href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/Studies/LinuxRNG/LinuxRNG_EN_V4_3.pdf">https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/Studies/LinuxRNG/LinuxRNG_EN_V4_3.pdf</a></li>
</ol>
</blockquote>
<p>さて、もちろんこの背景にはいくつか説明が必要だろう。まず、最近の Linux は <tt class="docutils literal">/dev/random</tt> を参照しても真の乱数を生成しない。もちろん真の乱数とは何かという議論はあるだろうが、ここで言いたいことはつまり、エントロピー源から得られた乱雑さだけをその都度使うことは無くなったということだ。言い換えれば、 <tt class="docutils literal">/dev/random</tt> はこれまでの <tt class="docutils literal">/dev/urandom</tt> と同じく、エントロピー源からシードを生成したり、フィードバックを受けたりすることはあるが、基本的にはブロックせず疑似乱数によって生成されるようになったということだ。これを聞くと Linux-Legacy-RNG の話はなんだったのかと多くの人は思うだろう。この背景は割と複雑で、政治的な事情も色々孕んでいるのだが、ひとまずそこは置いておいて、ひとまず ChaCha20-DRNG の概要を見ていこう。</p>
<p>ChaCha20-DRNG でも、Linux-Legacy-RNG と同じようにエントロピーを貯める入力プールがある。ただ、Linux-Regecy-RNG の時のようなブロッキングプール、非ブロッキングプールといったプールは存在せず、 <tt class="docutils literal">/dev/random</tt>、 <tt class="docutils literal">/dev/urandom</tt> は共通の一つの状態を参照する。状態は固定長のビット列領域で、ChaCha20 の乱数ストリーム生成に使用される。状態ははじめエントロピープールから生成されたシードで初期化され、その後は入力プールが更新されたかによらず入力プールの内容と状態のデータを使って状態を更新し続けながら、乱数生成をしていく。もちろん、入力プールに環境ノイズが入ればそれは都度反映されるし、環境ノイズが入らなくても暗号学的に安全な乱数生成が行われることになる。これにより、 <tt class="docutils literal">/dev/random</tt> と <tt class="docutils literal">/dev/urandom</tt> の違いは、一番最初のシード初期化が完了するまで待つか、それを待たずに警告のみでエントロピーの反映が甘いかもしれない乱数を警告込みでブロックしないで生成するかの違いになった。シード初期化自体も基本的には1秒ほどの短時間で終わるため、ほとんどの場合 <tt class="docutils literal">/dev/random</tt> と <tt class="docutils literal">/dev/urandom</tt> の違いを意識して使用する必要は無くなったわけだ。</p>
<p>さてこのような変更が受け入れ可能なら、なぜ Linux-Legacy-RNG では2つのデバイスの使い分けが必要だったのだろうか? まずこのような変更が可能になったのには、一つには乱数生成器が大きく改善されたというのがある。Linux-Legacy-RNG の時代は SHA1 実装だったのだが、ChaCha20-DRNG では BLAKE2 による実装になっており、攻撃耐性が色々向上している <a class="footnote-reference" href="#linux-random-improvement" id="auto-id-7">[2]</a>。この強化により、エントロピーをそこまで過剰に反映させなくても、初期化時に十分に反映されていればある程度安全性の高い乱数が生成されるようになったというのがある。もう一つは、そもそもブロッキングプールに対する暗号学的耐性への疑念があるということだ。これは結構昔から言われていたことなのだが、真の乱数を使えば攻撃耐性が備えられるというのは誤りであり、品質の向上に繋がるかも怪しい面が多いというのがある。環境ノイズはそもそも環境によって左右されるわけだが、逆に言えば環境が突然激変しない限り規則性を生む場合も多い。また、時間帯などで品質が大きく変わってくる。実際、環境ノイズだけを乱数の情報源として使用してしまうと、逆に攻撃耐性が下がるというのは割と知られており、むしろ環境ノイズを使うなら疑似乱数や状態をちょいちょい混合してやらないといけないというのが昨今のベストプラクティスで、 <tt class="docutils literal">/dev/random</tt> と <tt class="docutils literal">/dev/urandom</tt> の差が実際に安全性に大きい差があるかについては懐疑的な声も多かった。どちらもエントロピーの反映自体は行われているわけで、違いは単純にその量だけであり、SHA1 LFSR 実装ならばともかく、そこから脱却した今となってはその違いは大きいものではないということだ。また、 <tt class="docutils literal">/dev/random</tt> がブロックすることに至っては DoS 攻撃の要因にもなり兼ねないため、セキュリティ的に負の面もあった。このようなリスクに対して真面目に対処してまで、 <tt class="docutils literal">/dev/random</tt> にエントロピーを確実に反映させる必要があるのかという不満は Linux 開発者の間で割と上がってはおり、ChaCha20-DRNG ではその声が反映されたという形になる。将来的には、 <tt class="docutils literal">/dev/random</tt> と <tt class="docutils literal">/dev/urandom</tt> の中身を全く同じにする、 <tt class="docutils literal">/dev/urandom</tt> を廃止するという動きもある。もし、アリスが案件を引き受けたのが5年後だったら、もしかしたら今回の問題とは無縁でいられたかもしれない。</p>
<p>というわけで、最近の Linux ではあまり必要性がなくなってきているが、一応入力プールの状態の監視方法についてもまとめておこうと思う。入力プールの状態を監視する為、proc ファイルがいくつか用意されている。それぞれ以下のようになる:</p>
<dl class="docutils">
<dt><tt class="docutils literal">/proc/sys/kernel/random/poolsize</tt></dt>
<dd>入力プールのビットサイズを表す。</dd>
<dt><tt class="docutils literal">/proc/sys/kernel/random/entropy_avail</tt></dt>
<dd>入力プールのエントロピービットサイズを表す。これが <tt class="docutils literal">/proc/sys/kernel/random/poolsize</tt> と同じならエントロピーは十分にあるということで、 <tt class="docutils literal">0</tt> だとエントロピーが枯渇していることを表す。ChaCha20-DRNG では初期化後は基本 <tt class="docutils literal">/proc/sys/kernel/random/poolsize</tt> と同じになる。</dd>
</dl>
<p>他にもいくつかあるが、基本はこの2つを見ておけばいいだろう。node exporter にはこいつらの collector がデフォルトで有効になっていて、それぞれ <tt class="docutils literal">node_entropy_pool_size_bits</tt>、 <tt class="docutils literal">node_entropy_available_bits</tt> で見れる。この辺を監視していれば、アリスやボブももう少し早く原因に気づけたかもしれない。</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで今回は Java の <tt class="docutils literal">SecureRandom.getInstanceStrong()</tt> を使う際の注意点について紹介した。 <tt class="docutils literal">SecureRandom.getInstanceStrong()</tt> は Linux 環境では基本的には <tt class="docutils literal">/dev/random</tt> を参照する実装になり、 <tt class="docutils literal">/dev/random</tt> はエントロピーが不足するとブロックする挙動になるため注意が必要だ。また、付加価値が高く永続性が高い機密情報でもない限りデフォルトの <tt class="docutils literal">new SecureRandom()</tt> のインスタンスを使うので十分であり、そちらはブロックを行わないため問題が起きにくい。 <tt class="docutils literal">SecureRandom.getInstanceStrong()</tt> を単に名前が強そうだからという理由で使うのではなく、自身のサービスの特性に合うアルゴリズムをちゃんと選ぶのが重要だろうということだった。最も最近の Linux では事情が異なり、 <tt class="docutils literal">/dev/random</tt> と <tt class="docutils literal">/dev/urandom</tt> の違いがなくなりつつあるため、今後はその違いについて考慮する必要はなくなってくるだろう。</p>
<p><tt class="docutils literal">/dev/random</tt> を使ってはいけないみたいな話時々聞くが実際にどういう話なのか実は知らなかったので、今回のはためになった。最も、この知識がこれから役立つことはあまりなくなっていきそうだが。では、今回はこれで。</p>
<table class="docutils footnote" frame="void" id="linux-rng-history" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[1]</a></td><td>詳しい経緯は <a class="reference external" href="https://lwn.net/Articles/884875/">https://lwn.net/Articles/884875/</a> を参照するのが良いだろう。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="linux-random-improvement" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[2]</a></td><td><a class="reference external" href="https://www.zx2c4.com/projects/linux-rng-5.17-5.18/inside-linux-kernel-rng-presentation-sept-13-2022.pdf">https://www.zx2c4.com/projects/linux-rng-5.17-5.18/inside-linux-kernel-rng-presentation-sept-13-2022.pdf</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/02/use-securerandom-getinstancestrong-carefully.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/02/use-securerandom-getinstancestrong-carefully.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>HM(X): 多相と制約と推論と2023-01-24T12:49:16+09:002023-01-24T12:49:16+09:00Mizunashi Manatag:mizunashi-mana.github.io,2023-01-24:/blog/posts/2023/01/hmx-inference-with-constraints/<p>パラメータ多相を持つプログラミング言語は多いが,その多くは型パラメータの記述機能だけを持つわけではない …</p><p>パラメータ多相を持つプログラミング言語は多いが,その多くは型パラメータの記述機能だけを持つわけではない.例えば,Java ではパラメータ多相に加え,パラメータの変性を指定でき,その指定とサブタイプ関係によって受け入れるパラメータの範囲や挙動を変えたりできる.また,Haskell では型パラメータに対して,その型に付随した特定の機能を持つ保証を要求するような型制約を記述できる.他にも型パラメータに対して追加で条件を科すような機能を持つ言語は多い.もちろん,そのような言語が型推論の機能を持つ時,パラメータの制約に対しても考慮をしなければその言語のユーザ体験は著しく損なわれる.そのため,単純な多相型の推論機能だけでなく,制約も考慮した推論体系を搭載するのが普通だ.</p>
<p>そのような体系について,HM 推論をベースに,汎用的な推論フレームワークを提供してくれるのが HM(X) 型推論である.HM(X) 推論は制約の体系 X に対して HM 推論を拡張した推論体系を提供してくれる.今回はそのフレームワークを紹介したいと思う.なお,題材は以下:</p>
<blockquote>
Martin Odersky, Martin Sulzmann, and Martin Wehr. Type inference with constrained types. Theory and Practice of Object Systems, 5:35–55, 1 1999.</blockquote>
<p>ただし,上の題材はかなり制約体系を抽象化しており,実装屋としては結構扱いにくいので,今回は</p>
<blockquote>
Dimitrios Vytiniotis, Simon Peyton Jones, Tom Schrijvers, and Martin Sulzmann. Outsidein(x): Modular type inference with local assumptions. Journal of Functional Programming, 21:333–412, 9 2011.</blockquote>
<p>の文献から着想を得て制約体系の方はかなり具象化した話をしていく.元の話がどういうものか知りたい場合は元文献を参照してもらうのが良いだろう.また,HM 推論の話を理解していることが前提となる.HM 推論については, <a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/">前回</a> 解説記事を書いたのでそちらをまず参照してもらうのがいいだろう.</p>
<div class="section" id="auto-id-2">
<h2>制約<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今回扱う言語は基本的には Let 多相を搭載した型付ラムダ計算の拡張になる:</p>
<img alt="構文要素" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/syntax.png"/>
<p>本来,HM(X) は制約に関して具体的な構文要素を用意せず,一定の性質を持ち推論解決アルゴリズムが存在するような抽象的な制約システムに対しての推論体系を提供する.ただ,今回はもう少し掘り下げて,具体例と制約解決アルゴリズムについても言及するため,あえて制約についても具体的な構文を用意している.各構文要素は以下のようになる:</p>
<dl class="docutils">
<dt>型コンストラクタ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi></mrow><annotation encoding="application/x-tex">T</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span></span></span></span></dt>
<dd>型の等価判定の基本単位.原始的に関数型のコンストラクタ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>→</mo></mrow><annotation encoding="application/x-tex">\to</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">→</span></span></span></span></span> を含んでいる.それぞれの言語によって導入される型コンストラクタは変わる.</dd>
<dt>制約コンストラクタ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span></dt>
<dd>制約の等価判定の基本単位.それぞれの言語によって導入される制約コンストラクタは変わる.</dd>
<dt>型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span></dt>
<dd>型を表す項.変数と型コンストラクタから生成される.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" rspace="0em">→</mo><mtext> </mtext><msub><mi>τ</mi><mn>1</mn></msub><mtext> </mtext><msub><mi>τ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">{\to}\; \tau_1\; \tau_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mrel">→</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>τ</mi><mn>1</mn></msub><mo>→</mo><msub><mi>τ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">\tau_1 \to \tau_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> と表記することもある.</dd>
<dt>制約 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Q</mi></mrow><annotation encoding="application/x-tex">Q</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span></span></dt>
<dd>制約を表す項.制約がないことを表す空制約 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">\epsilon</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span></span></span></span></span>,制約の結合,型制約,等価制約から生成される.</dd>
<dt>型スキーム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span></dt>
<dd>多相型を表す項.型パラメータ,パラメータを含んだ制約,パラメータを含んだ型から生成される.</dd>
<dt>式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span></dt>
<dd>式を表す項.変数,λ抽象,適用,let 式から生成される.</dd>
</dl>
<p>制約はそのまま言語機能として組み込んでもいいが,elaboration の対象として,他の言語機能を模倣するのにも応用できる.例えば,加算,乗算ができる型とそうでない型がある言語で,多相的な加算演算子,乗算演算子を提供したい場合を考える.具体的には次のようなコンストラクタを提供する言語を考える:</p>
<img alt="多相的な加算,乗算を提供する言語のコンストラクタ" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/num-constrained-syntax.png"/>
<p>この場合に,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><mo>=</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mrow><mi>p</mi><mi>l</mi><mi>u</mi><mi>s</mi></mrow><mtext> </mtext><mi>x</mi><mtext> </mtext><mi>x</mi><mtext> </mtext><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><mtext> </mtext><mn>1.0</mn></mrow><annotation encoding="application/x-tex">
\mathbf{let}\;\mathit{double} = \lambda x\ldotp \mathit{plus}\; x\; x\; \mathbf{in}\; \mathit{double}\; 1.0
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">let</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">double</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">plus</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">in</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">double</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1.0</span></span></span></span></span></div>
<p>のようなプログラムにおいて, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mi>l</mi><mi>u</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{plus}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">plus</span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>α</mi><mo separator="true">.</mo><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><mi>α</mi><mo>⇒</mo><mi>α</mi><mo>→</mo><mi>α</mi><mo>→</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\forall \alpha\ldotp \mathbf{Num}\; \alpha \Rightarrow \alpha \to \alpha \to \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span>,即ち <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><annotation encoding="application/x-tex">\mathbf{Num}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Num</span></span></span></span></span></span> 制約を満たす型パラメータ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> の引数を2つ受け取りその加算結果を計算して返すような多相関数として提供され,また <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1.0</mn></mrow><annotation encoding="application/x-tex">1.0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1.0</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span> 型の値として提供されたとき,それを元に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">\mathit{double}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">double</span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>α</mi><mo separator="true">.</mo><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><mi>α</mi><mo>⇒</mo><mi>α</mi><mo>→</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\forall \alpha\ldotp \mathbf{Num}\; \alpha \Rightarrow \alpha \to \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> として推論され,let 式の主部では <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">\mathit{double}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">double</span></span></span></span></span></span> の型パラメータ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span> 型にインスタンス化され,上記プログラム全体としては <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span> 型の式と推論される,もし <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">\mathit{double}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">double</span></span></span></span></span></span> に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">b</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">l</mi></mrow><annotation encoding="application/x-tex">\mathbf{bool}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">bool</span></span></span></span></span></span> 型の値を渡すと型推論が失敗する,というようにパラメータに関して何かしら条件を科すような機能を持った言語について,コンストラクタと提供する原始関数につける制約を工夫することで HM(X) の枠組みの推論体系を流用できるというわけだ.原著でも,サブタイプ関係を伴った推論や多相レコードを使った項への推論への応用例を挙げている.ま,動機としてはそんな感じ.</p>
</div>
<div class="section" id="auto-id-3">
<h2>型推論<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>では,具体的に型システムと推論体系を見ていく.まず,型システムを見ていくが,その前に環境を用意しておく:</p>
<img alt="環境の構文定義" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/env-syntax.png"/>
<p>今回の制約付き Let 多相では,型付けを型環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span> の他に制約環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> を元に判定する.型環境は言わずもがなだと思うが,制約環境とは今充足していることが保証される制約が入っている環境だ.今回は,制約と同じものしか入れないことにするが,例えば制約環境のみ特別な制約を導入することも可能だ.このような環境に対して,制約含意と型システムが定義される.</p>
<p>制約付き Let 多相の型システムは制約含意 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo>⊩</mo><mi>Q</mi></mrow><annotation encoding="application/x-tex">C \Vdash Q</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6922em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⊩</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span></span> に依存する.制約含意とは制約環境から導かれる制約の判定のことで,以下のようになる:</p>
<img alt="制約含意の規則" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/constraint-entailment.png"/>
<p>基本的な含意の規則は最初の2つで,後は型の等価判定制約に関する要求規則という感じだ.型の等価判定に対して特別な要求規則が入っているのは,おまけという意味合いも強いだろう.単純な構文的等価性の範疇を超えた型の等価性を扱う言語も多いし,等価性がパラメータの制約により影響を受ける言語も多い.その為,型の等価性,要はキャスティングについての拡張も考慮できるように型の等価判定を加えているという面が強くそこまで本質的な機能ではないと思われる.ま,これに関しては型判定の規則も見てみる方がいいと思うので,型判定の規則も示しておく:</p>
<img alt="HM(X) の型判定規則" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/type-system.png"/>
<p><a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/">前回</a> は Let 多相のイントロも兼ねてアルゴリズムに素直に対応する型システムを紹介したが,今回は一般化とインスタンス化を規則として分けて書いている.ただ比較がしにくいと思うので,HM(X) での加筆点を赤で示している.この赤の部分がなければ,普通の Let 多相の型規則ということになる.変数以外の式は一般化をしない限り多相型でない単相型の型でしか型付できず,部分項についても単相化されていることを要求している.let 式のみ束縛部分で使用する式に限り型スキームで型付されていることが許される.最後の2つの規則が一般化とインスタンス化に対応し,一般化では新たなパラメータと制約を導入することができ,インスタンス化ではパラメータ全てに単相な型を割り当てることと制約が満たされていることが要求される <a class="footnote-reference" href="#hmx-constraint-satisfiability" id="auto-id-4">[1]</a>.また,型の等価判定が成り立つ範囲ではキャストができるというのが,最後から3つ目の規則になる.</p>
<p>インスタンス化では制約含意を仮定においているが,これと制約含意の最後の規則により,型の等価判定の範囲であればインスタンス化する型を実際の型制約で使った型と同じにしなくても良くなる.ただ,導出としては制約含意での制約のキャストをするのでも,一度インスタンス化してからキャストの規則を使って型を変えるのでも問題ない.このキャストの規則と制約含意の規則の釣り合いが取れるようにというのと,無茶なキャストができないように制約含意の方にも型の等価制約に関する幾つかの要求規則が仕込まれているという感じだ.</p>
<p>さて,見ての通り HM(X) の型システムはそれほど大した拡張ではない.キャストの規則を追加して,制約込みで一般化できるようにし,インスタンス化の際制約のチェックが入るようになっただけだ.実際,推論の方もそこまで複雑な拡張を入れないで実現できる:</p>
<img alt="HM(X) の型推論規則" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/type-inference.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi><mi>e</mi><mi>n</mi></mrow><annotation encoding="application/x-tex">\mathit{gen}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">gen</span></span></span></span></span></span> は一般化関数で,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>g</mi><mi>e</mi><mi>n</mi></mrow><mo stretchy="false">(</mo><mi mathvariant="normal">Γ</mi><mo separator="true">,</mo><mi>Q</mi><mo separator="true">,</mo><mi>τ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathit{gen}(\Gamma, Q, \tau)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">gen</span></span><span class="mopen">(</span><span class="mord">Γ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">Q</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">)</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>α</mi><mo>⃗</mo></mover><mo>=</mo><mo stretchy="false">(</mo><mrow><mi>f</mi><mi>t</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><mi>Q</mi><mo stretchy="false">)</mo><mo>∪</mo><mrow><mi>f</mi><mi>t</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><mi>τ</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mi mathvariant="normal">\</mi><mrow><mi>f</mi><mi>t</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><mi mathvariant="normal">Γ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\vec{\alpha} = (\mathit{ftv}(Q) \cup \mathit{ftv}(\tau)) \backslash \mathit{ftv}(\Gamma)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.714em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2077em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg height="0.714em" preserveaspectratio="xMinYMin" style="width:0.471em" viewbox="0 0 471 714" width="0.471em" xmlns="http://www.w3.org/2000/svg"><path d="M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5
3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11
10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63
-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1
-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59
H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359
c-16-25.333-24-45-24-59z"></path></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ftv</span></span><span class="mopen">(</span><span class="mord mathnormal">Q</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ftv</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">))</span><span class="mord">\</span><span class="mord"><span class="mord mathit">ftv</span></span><span class="mopen">(</span><span class="mord">Γ</span><span class="mclose">)</span></span></span></span></span> をパラメータとし,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mover accent="true"><mi>α</mi><mo>⃗</mo></mover><mo separator="true">.</mo><mi>Q</mi><mo>⇒</mo><mi>τ</mi></mrow><annotation encoding="application/x-tex">\forall \vec{\alpha}\ldotp Q \Rightarrow \tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9084em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2077em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg height="0.714em" preserveaspectratio="xMinYMin" style="width:0.471em" viewbox="0 0 471 714" width="0.471em" xmlns="http://www.w3.org/2000/svg"><path d="M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5
3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11
10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63
-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1
-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59
H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359
c-16-25.333-24-45-24-59z"></path></svg></span></span></span></span></span></span></span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> を返す <a class="footnote-reference" href="#hmx-generalization" id="auto-id-5">[2]</a>.</p>
<p>さて,この時,制約解決関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>o</mi><mi>l</mi><mi>v</mi></mrow><annotation encoding="application/x-tex">\mathit{solv}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">solv</span></span></span></span></span></span>,式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span>,環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi></mrow><annotation encoding="application/x-tex">\Gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span></span></span></span></span>,制約環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">W</mi><mo stretchy="false">(</mo><mi mathvariant="normal">Γ</mi><mo separator="true">,</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>Q</mi><mo separator="true">,</mo><mi>τ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{W}(\Gamma, e) = (Q, \tau)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal" style="margin-right:0.08222em;">W</span><span class="mopen">(</span><span class="mord">Γ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">Q</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">)</span></span></span></span></span> で,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>s</mi><mi>o</mi><mi>l</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><mi>C</mi><mo separator="true">,</mo><mi>Q</mi><mo stretchy="false">)</mo><mo>=</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">\mathit{solv}(C, Q) = S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">solv</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">Q</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span> の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi><mi>τ</mi></mrow><annotation encoding="application/x-tex">S\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span>,それ以外の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> を返せば,型推論アルゴリズムとなる.この時,制約解決をいい感じに設計すると,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo separator="true">;</mo><mi mathvariant="normal">Γ</mi><mo>⊢</mo><mi>e</mi><mo>:</mo><mi>S</mi><mi>τ</mi></mrow><annotation encoding="application/x-tex">C; \Gamma \vdash e: S\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> となるような推論が行えるアルゴリズムになる.今回は制約解決は具体的に後で構築し,あまり抽象的に「いい感じの設計」というのがどういう性質を指すかは立ち入らない.興味があれば元論文を読んでみるのがいいだろう.ま,基本的には制約解決の条件は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo>⊩</mo><mi>Q</mi></mrow><annotation encoding="application/x-tex">C \Vdash Q</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6922em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⊩</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span></span> を満たし,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Q</mi></mrow><annotation encoding="application/x-tex">Q</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span></span> に含まれる型の等価性に関する制約が全て置換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi></mrow><annotation encoding="application/x-tex">S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span> に反映されていることという感じだ.こんな感じの設計を満たせば,大体制約込みの型推論になる.</p>
<p>一般化が制約込みで行われるようになること,単一化が型の等価性制約の追加,そして最後に制約解決が入ることのみが異なるが,基本アルゴリズム W と構成は同じだ.このように,HM(X) では与えられる制約システムにおいて,制約解決の方法が与えられた時,それを元に HM 推論を構成はほとんど変えずに拡張できる.</p>
<p>例えば,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><mo>=</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mrow><mi>p</mi><mi>l</mi><mi>u</mi><mi>s</mi></mrow><mtext> </mtext><mi>x</mi><mtext> </mtext><mi>x</mi><mtext> </mtext><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><mtext> </mtext><mn>1.0</mn></mrow><annotation encoding="application/x-tex">
\mathbf{let}\;\mathit{double} = \lambda x\ldotp \mathit{plus}\; x\; x\; \mathbf{in}\; \mathit{double}\; 1.0
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">let</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">double</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">plus</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">in</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">double</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1.0</span></span></span></span></span></div>
<p>について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo>=</mo><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">C = \mathbf{Num}\; \mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi><mo>=</mo><mn>1.0</mn><mo>:</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo>+</mo><mrow><mi>p</mi><mi>l</mi><mi>u</mi><mi>s</mi></mrow><mo>:</mo><mi mathvariant="normal">∀</mi><mi>α</mi><mo separator="true">.</mo><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><mi>α</mi><mo>⇒</mo><mi>α</mi><mo>→</mo><mi>α</mi><mo>→</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\Gamma = 1.0: \mathbf{float} + \mathit{plus}: \forall \alpha\ldotp \mathbf{Num}\; \alpha \Rightarrow \alpha \to \alpha \to \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1.0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">plus</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> の下での型推論を考えてみる.この時,まずは以下のように,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">W</mi></mrow><annotation encoding="application/x-tex">\mathcal{W}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathcal" style="margin-right:0.08222em;">W</span></span></span></span></span> による制約と型の生成が行われる:</p>
<img alt="HM(X) の型推論例" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/example-type-inference-generation.png"/>
<p>HM 型推論のアルゴリズム W に比べ,各所での単一化が起きずただ型の等価制約だけがどんどん増えていく.その等価制約に加え,必要な型制約も加えられ,最終的に変数を含む型と制約が生成される.これに対して,さらに <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">s</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">v</mi></mrow><mo stretchy="false">(</mo><mi>C</mi><mo separator="true">,</mo><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><msub><mi>β</mi><mn>6</mn></msub><mo>∧</mo><mo stretchy="false">(</mo><msub><mi>β</mi><mn>6</mn></msub><mo>→</mo><msub><mi>β</mi><mn>6</mn></msub><mo>→</mo><msub><mi>β</mi><mn>6</mn></msub><mo>≃</mo><msub><mi>β</mi><mn>5</mn></msub><mo>→</mo><msub><mi>β</mi><mn>7</mn></msub><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><msub><mi>β</mi><mn>7</mn></msub><mo>≃</mo><msub><mi>β</mi><mn>5</mn></msub><mo>→</mo><msub><mi>β</mi><mn>8</mn></msub><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><msub><mi>β</mi><mn>5</mn></msub><mo>→</mo><msub><mi>β</mi><mn>8</mn></msub><mo>≃</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><msub><mi>β</mi><mn>9</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><mi>θ</mi></mrow><annotation encoding="application/x-tex">\mathrm{solv}(C, \mathbf{Num}\; \beta_6 \land (\beta_6 \to \beta_6 \to \beta_6 \simeq \beta_5 \to \beta_7) \land (\beta_7 \simeq \beta_5 \to \beta_8) \land (\beta_5 \to \beta_8 \simeq \mathbf{float} \to \beta_9)) = \theta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm" style="margin-right:0.01389em;">solv</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span></span></span> により,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><mo stretchy="false">(</mo><msub><mi>β</mi><mn>5</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mi>θ</mi><mo stretchy="false">(</mo><msub><mi>β</mi><mn>6</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mi>θ</mi><mo stretchy="false">(</mo><msub><mi>β</mi><mn>8</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mi>θ</mi><mo stretchy="false">(</mo><msub><mi>β</mi><mn>9</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">\theta(\beta_5) = \theta(\beta_6) = \theta(\beta_8) = \theta(\beta_9) = \mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span>, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><mo stretchy="false">(</mo><msub><mi>β</mi><mn>7</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">\theta(\beta_7) = \mathbf{float} \to \mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span> となるような置換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi></mrow><annotation encoding="application/x-tex">\theta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span></span></span> が生成されることになり,最終的に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><msub><mi>β</mi><mn>9</mn></msub><mo>=</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">\theta\beta_9 = \mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span> が推論される型になる.このように,HM(X) では制約の生成が主な担当であり,その制約が妥当か検証し,制約から置換を生成することができれば,妥当な型が出力される.ただ,そのような制約解決をうまく定義するのはそれぞれの制約体系に任されることとなる.</p>
</div>
<div class="section" id="auto-id-6">
<h2>制約解決<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,HM(X) は制約を考慮した推論を,制約解決の方法が与えられた時に提供してくれる.最後にこの制約解決の方法についても言及しておこう.HM(X) 自体は基本これらの方法はパラメータとして与えられることが前提になっており,それを元に推論を提供してくれる体系なのだが,具体的に制約システムの方についても言及しておいた方がイメージがつきやすいだろう.</p>
<p>制約解決の役割は大きく2つある.1つは,型の等価制約からそれに合う置換を作成することだ.これは HM 推論での単一化に当たる.HM(X) では等価性が単純な構文的等価性の枠組みを超えることがあるかもしれない為,そのような体系にも耐えられるよう制約から置換を作成する.もう1つは制約の妥当性検証だ.つまり,推論された制約が満たされるべきものかを検証するということだ.この2つの役割を実現する為,制約解決はかなり段階を踏むことになる.</p>
<p>まず,制約を扱いやすいように原始制約の集合に変換する方法を用意しておく:</p>
<img alt="制約集合への変換" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/constraint-flatten.png"/>
<p>原始制約とは,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi><mover accent="true"><mi>τ</mi><mo>⃗</mo></mover></mrow><annotation encoding="application/x-tex">D \vec{\tau}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.714em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2077em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg height="0.714em" preserveaspectratio="xMinYMin" style="width:0.471em" viewbox="0 0 471 714" width="0.471em" xmlns="http://www.w3.org/2000/svg"><path d="M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5
3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11
10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63
-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1
-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59
H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359
c-16-25.333-24-45-24-59z"></path></svg></span></span></span></span></span></span></span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>τ</mi><mn>1</mn></msub><mo>≃</mo><msub><mi>τ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">\tau_1 \simeq \tau_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6138em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> のことで,もうそれ以上分解できないような制約のこと.今回は,この関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">f</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{flat}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">flat</span></span></span></span></span></span> により変換された集合に対して,書き換えシステムにより制約解決を行なっていく.書き換えシステムは,制約環境を取り,原始制約の集合をより単純な原始制約に変換するか,妥当でない原始制約が含まれていることを表す <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> に書き換えを行う.具体的には以下のようなシステムにより制約解決を行える:</p>
<img alt="制約解決システム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/constraint-solving-system.png"/>
<p>この制約解決システムは最終的に,</p>
<ul class="simple">
<li>元の制約に現れる自由変数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> に対して,高々一つだけ代表的な型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> を伴った等価制約 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>≃</mo><mi>τ</mi></mrow><annotation encoding="application/x-tex">\alpha \simeq \tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span></li>
<li>制約環境から解決できなかった制約 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi><mover accent="true"><mi>τ</mi><mo>⃗</mo></mover><mo>∉</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">D \vec{\tau} \not\in C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9084em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2077em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg height="0.714em" preserveaspectratio="xMinYMin" style="width:0.471em" viewbox="0 0 471 714" width="0.471em" xmlns="http://www.w3.org/2000/svg"><path d="M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5
3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11
10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63
-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1
-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59
H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359
c-16-25.333-24-45-24-59z"></path></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
</ul>
<p>だけを含む原始制約の集合に変換するか,制約が妥当でないことを表す <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> に変換を行う.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≺</mo></mrow><annotation encoding="application/x-tex">\prec</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel">≺</span></span></span></span></span> は等価制約を正規化するための関係で,何でもいいが変数に対しての全順序が提供された時,それを型全体に対して拡張する.与えられた原始制約の集合に含まれる全ての等価制約は,最初の3つの等価制約解決の規則と,4つ目の規則により,最終的にこの関係を遵守することになる.もう一つ,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋘</mo></mrow><annotation encoding="application/x-tex">\lll</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.585em;vertical-align:-0.0352em;"></span><span class="mrel amsrm">⋘</span></span></span></span></span> は正規化された等価制約であることを表す関係になっており,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≺</mo></mrow><annotation encoding="application/x-tex">\prec</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel">≺</span></span></span></span></span> に加えて,妥当でない再帰的な等価制約でないことを表す.やはり,与えられた原始制約の集合に含まれる全ての等価制約は,最終的にこの関係を遵守するように変換される.残りの6から8番目の規則は最終的な置換を構成するための変数に紐づく型の単一化規則,最後の規則は制約環境からの制約の解決の規則になる.制約解決は,この書き換えシステムの正規系 <a class="footnote-reference" href="#confluence-of-constraint-solving" id="auto-id-7">[3]</a> を元に,置換を構成することで定義される:</p>
<img alt="制約解決による置換の構成" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/constraint-solving.png"/>
<p>基本的に置換は書き換えにより生成された等価制約を元に構成される.ただ,等価制約には言及されない変数が存在することもある.そして,この変数が残っている状態だと制約解決がうまく行われないが,変数をうまく具体化すれば制約を満たすような状況が考えられる.例えば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><mi>β</mi></mrow><annotation encoding="application/x-tex">\mathbf{Num}\; \beta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span></span></span></span></span> のような制約が書き換えの結果残ったとして,制約環境に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">\mathbf{Num}\; \mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span> のような制約が含まれていることを考える.この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi></mrow><annotation encoding="application/x-tex">\beta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span></span></span></span></span> が置換に含まれなかったとしても,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><mo stretchy="false">(</mo><mi>β</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">\theta(\beta) = \mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span> というような置換を加えれば制約を満たせる.このような制約を考慮したデフォルティングの余地を残すため,上記の定義では置換を具体的に構成していない.ただ,デフォルティングは諦めるという選択肢もあり,その場合は書き換えシステムのみで置換を構成できることになる.さて,この置換の構成を元に,最終的に以下のようにして制約を考慮した推論が行える:</p>
<img alt="制約解決を踏まえた型推論" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/type-inference-with-constraints.png"/>
<p>この時,推論を行なった型について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo separator="true">;</mo><mi mathvariant="normal">Γ</mi><mo>⊢</mo><mi>e</mi><mo>:</mo><mi>θ</mi><mi>τ</mi></mrow><annotation encoding="application/x-tex">C; \Gamma \vdash e: \theta\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> が成り立つ.例えば,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><mo>=</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mrow><mi>p</mi><mi>l</mi><mi>u</mi><mi>s</mi></mrow><mtext> </mtext><mi>x</mi><mtext> </mtext><mi>x</mi><mtext> </mtext><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><mtext> </mtext><mn>1.0</mn></mrow><annotation encoding="application/x-tex">
\mathbf{let}\;\mathit{double} = \lambda x\ldotp \mathit{plus}\; x\; x\; \mathbf{in}\; \mathit{double}\; 1.0
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">let</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">double</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">plus</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">in</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">double</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1.0</span></span></span></span></span></div>
<p>について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo>=</mo><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">C = \mathbf{Num}\; \mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi><mo>=</mo><mn>1.0</mn><mo>:</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo>+</mo><mrow><mi>p</mi><mi>l</mi><mi>u</mi><mi>s</mi></mrow><mo>:</mo><mi mathvariant="normal">∀</mi><mi>α</mi><mo separator="true">.</mo><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><mi>α</mi><mo>⇒</mo><mi>α</mi><mo>→</mo><mi>α</mi><mo>→</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\Gamma = 1.0: \mathbf{float} + \mathit{plus}: \forall \alpha\ldotp \mathbf{Num}\; \alpha \Rightarrow \alpha \to \alpha \to \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1.0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">plus</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> の下での型推論を考えてみる.上記で,第一段階の制約と型の生成の結果は,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">W</mi><mo stretchy="false">(</mo><mi mathvariant="normal">Γ</mi><mo separator="true">,</mo><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><mo>=</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mrow><mi>p</mi><mi>l</mi><mi>u</mi><mi>s</mi></mrow><mtext> </mtext><mi>x</mi><mtext> </mtext><mi>x</mi><mtext> </mtext><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mrow><mi>d</mi><mi>o</mi><mi>u</mi><mi>b</mi><mi>l</mi><mi>e</mi></mrow><mtext> </mtext><mn>1.0</mn><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mrow><mi mathvariant="bold">N</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">m</mi></mrow><mtext> </mtext><msub><mi>β</mi><mn>6</mn></msub><mo>∧</mo><mo stretchy="false">(</mo><msub><mi>β</mi><mn>6</mn></msub><mo>→</mo><msub><mi>β</mi><mn>6</mn></msub><mo>→</mo><msub><mi>β</mi><mn>6</mn></msub><mo>≃</mo><msub><mi>β</mi><mn>5</mn></msub><mo>→</mo><msub><mi>β</mi><mn>7</mn></msub><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><msub><mi>β</mi><mn>7</mn></msub><mo>≃</mo><msub><mi>β</mi><mn>5</mn></msub><mo>→</mo><msub><mi>β</mi><mn>8</mn></msub><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><msub><mi>β</mi><mn>5</mn></msub><mo>→</mo><msub><mi>β</mi><mn>8</mn></msub><mo>≃</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><msub><mi>β</mi><mn>9</mn></msub><mo stretchy="false">)</mo><mo separator="true">,</mo><msub><mi>β</mi><mn>9</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\mathcal{W}(\Gamma, \mathbf{let}\;\mathit{double} = \lambda x\ldotp \mathit{plus}\; x\; x\; \mathbf{in}\; \mathit{double}\; 1.0) = (\mathbf{Num}\; \beta_6 \land (\beta_6 \to \beta_6 \to \beta_6 \simeq \beta_5 \to \beta_7) \land (\beta_7 \simeq \beta_5 \to \beta_8) \land (\beta_5 \to \beta_8 \simeq \mathbf{float} \to \beta_9), \beta_9)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal" style="margin-right:0.08222em;">W</span><span class="mopen">(</span><span class="mord">Γ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">let</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">double</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">plus</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">in</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">double</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1.0</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathbf">Num</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>であることが分かっている.後はこの生成された制約を書き換えシステムにより書き換えていく.なお,変数の順序は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≤</mo><mi>m</mi></mrow><annotation encoding="application/x-tex">n \leq m</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span></span> の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>β</mi><mi>n</mi></msub><mo>≤</mo><msub><mi>β</mi><mi>m</mi></msub></mrow><annotation encoding="application/x-tex">\beta_n \leq \beta_m</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> と考える.この時,書き換えの過程は以下のようになる:</p>
<img alt="制約解決システムによる書き換えの過程" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/example-constraint-solving.png"/>
<p>分かりやすいように各ステップで書き換え対象となっている原始制約を,赤で記している.書き換えの過程で型コンストラクタを含む等価制約がどんどん分解され,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋘</mo></mrow><annotation encoding="application/x-tex">\lll</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.585em;vertical-align:-0.0352em;"></span><span class="mrel amsrm">⋘</span></span></span></span></span> の関係を満たすよう整理されていき,最終的に単一化により型が具体化されていく様子が分かるだろう.この結果から,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><mo>=</mo><mo stretchy="false">[</mo><msub><mi>β</mi><mn>5</mn></msub><mo>←</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo separator="true">,</mo><msub><mi>β</mi><mn>6</mn></msub><mo>←</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo separator="true">,</mo><msub><mi>β</mi><mn>7</mn></msub><mo>←</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo separator="true">,</mo><msub><mi>β</mi><mn>8</mn></msub><mo>←</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo separator="true">,</mo><msub><mi>β</mi><mn>9</mn></msub><mo>←</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">\theta = [\beta_5 \leftarrow \mathbf{float}, \beta_6 \leftarrow \mathbf{float}, \beta_7 \leftarrow \mathbf{float} \to \mathbf{float}, \beta_8 \leftarrow \mathbf{float}, \beta_9 \leftarrow \mathbf{float}]</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathbf">float</span></span><span class="mclose">]</span></span></span></span></span> のような置換が条件を満足することが分かり,最終的に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi><msub><mi>β</mi><mn>9</mn></msub><mo>=</mo><mrow><mi mathvariant="bold">f</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">\theta\beta_9 = \mathbf{float}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">float</span></span></span></span></span></span> が推論結果として得られることになる.</p>
</div>
<div class="section" id="auto-id-8">
<h2>制約解決と完全性<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,HM(X) は基本的に制約の生成だけを担当し,その制約を解決する仕組みは別途制約体系として与える必要があった.上記では,その仕組みの具体例を紹介した.ところが,上記で与えた制約解決は実はかなり不完全である.つまり,本来制約解決を行えるようなものに関して,幾つか取りこぼしが生じるということだ.例えば,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>≃</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mn mathvariant="bold">64</mn></mrow><mo separator="true">;</mo><mi>f</mi><mo>:</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>+</mo><mn>1</mn><mo>:</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mn mathvariant="bold">64</mn></mrow><mo>⊢</mo><mi>f</mi><mtext> </mtext><mn>1</mn><mo>:</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">
\mathbf{Int} \simeq \mathbf{Int64}; f: \mathbf{Int} \to \mathbf{Int} + 1: \mathbf{Int64} \vdash f\; 1: \mathbf{Int}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">Int64</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7694em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">Int64</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span></span></span></span></span></div>
<p>のような型付について考えてみる.この型付が正しいことは,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo>=</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>≃</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mn mathvariant="bold">64</mn></mrow></mrow><annotation encoding="application/x-tex">C = \mathbf{Int} \simeq \mathbf{Int64}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int64</span></span></span></span></span></span>, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Γ</mi><mo>=</mo><mi>f</mi><mo>:</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>+</mo><mn>1</mn><mo>:</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mn mathvariant="bold">64</mn></mrow></mrow><annotation encoding="application/x-tex">\Gamma = f: \mathbf{Int} \to \mathbf{Int} + 1: \mathbf{Int64}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7694em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int64</span></span></span></span></span></span> と置いた時,以下のように確かめられる:</p>
<img alt="型付の例" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2023/01/hmx-inference-with-constraints/hmx-inference-with-constraints/example-typing-for-casting.png"/>
<p>しかしこの式について,上記の型推論アルゴリズムを適用してみると,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">W</mi><mo stretchy="false">(</mo><mi mathvariant="normal">Γ</mi><mo separator="true">,</mo><mi>f</mi><mtext> </mtext><mn>1</mn><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>≃</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mn mathvariant="bold">64</mn></mrow><mo>→</mo><mi>β</mi><mo separator="true">,</mo><mi>β</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{W}(\Gamma, f\; 1) = (\mathbf{Int} \to \mathbf{Int} \simeq \mathbf{Int64} \to \beta, \beta)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal" style="margin-right:0.08222em;">W</span><span class="mopen">(</span><span class="mord">Γ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int64</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mclose">)</span></span></span></span></span> となり,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo>⊢</mo><mo stretchy="false">{</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>≃</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mn mathvariant="bold">64</mn></mrow><mo>→</mo><mi>β</mi><mo stretchy="false">}</mo><mo>→</mo><mo stretchy="false">{</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>≃</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mn mathvariant="bold">64</mn></mrow><mo separator="true">,</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mo>≃</mo><mi>β</mi><mo stretchy="false">}</mo><mo>→</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">C \vdash \{\mathbf{Int} \to \mathbf{Int} \simeq \mathbf{Int64} \to \beta\} \to \{\mathbf{Int} \simeq \mathbf{Int64}, \mathbf{Int} \simeq \beta\} \to \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int64</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8805em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">Int64</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> となるため,型推論に失敗することになる.これは制約解決が,等価制約の解決について制約環境を参照しないことによる.</p>
<p>HM(X) は制約解決がうまく設計できれば,ある程度緩めた形ではあるが完全な推論を提供する.ところが,上記でも述べたとおり,HM(X) の主な役目は制約の生成であり,制約解決は何らかの形で別途与えられなければならず,完全さはその与えられた制約解決に大きく依存する.そして,この制約解決の設計こそが難関だったりする.制約解決をある程度計算時間を抑えつつ,完全性を保証するものにしたかったら,ある程度機能を絞るか,細かい制約の使用条件を課す必要が出てくる.これは各種言語苦労している部分で結構アドホックな対応になりがち.つまり,HM(X) は HM 推論の簡易な拡張としての立場を取りつつ,制約体系をパラメータとして様々な体系に適用できることを売りにしているわけだが,実際には制約体系をパラメータとして与えるように設計すること自体はそれほど簡易とは限らないわけだ.さらに,実は HM 推論を土台にしつつそのまま各体系に合わせて推論規則を拡張する方が素直にいく場合も多いというのが実情ではある.ま,ここら辺は,実用寄りの応用理論ではよく起こりがちのジレンマというやつだろう.</p>
<p>なお,今回あげた制約解決は</p>
<blockquote>
Dimitrios Vytiniotis, Simon Peyton Jones, Tom Schrijvers, and Martin Sulzmann. Outsidein(x): Modular type inference with local assumptions. Journal of Functional Programming, 21:333–412, 9 2011.</blockquote>
<p>の一部を取り出したものとなっていて,この文献は Haskell の型推論の基礎理論となっているんだが,元文献の制約解決では type エイリアス,type family などを扱うため,もう少し強力な書き換えシステムと制約環境への追加条件などを紹介している.このような,HM(X) を基礎としつつ制約解決を頑張って設計し拡充していく方向性は良し悪しはあるものの,参考になる部分も多いだろう.ま,まさに参考実装としての側面では HM(X) は結構有用だ.ただ,上記の文献でも完全さはかなり諦めている.この辺は,実装としては完全さにこだわるよりも実用に耐えることが一般的には重視されるという面もあるが,HM(X) 自体の完全性を満たすように制約解決を設計する難しさがあるという面は否めないだろう.その辺は,HM(X) を基礎として型推論を実装する戦略を取る際は頭に入れておくのが良いと思う.</p>
</div>
<div class="section" id="auto-id-9">
<h2>まとめ<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,制約を考慮した HM 推論の拡張フレームワーク HM(X) の紹介だった.HM(X) は HM 推論を少しの工夫を入れることで制約という新たな要素に対応できるようにしている.ただ,HM(X) の本質は,HM 推論を制約生成も合わせて行うよう拡張している部分で,推論として完成するにはさらに生成された制約を解決し,置換をうまく生成するような仕組みが別途必要になる.そして,HM(X) 自体は割と簡易的な拡張に見えて,実際は制約解決の仕組みを作ることこそが難関という面がある.その為,HM(X) が提供している範囲のアルゴリズムだけでは,そのまま応用は難しいという側面もある.今回は,一応制約解決の方も具体的に構築例を示してみた.ま,何かの参考になればという感じ.</p>
<p>なお,Pottier 先生の ATTaPL の 10 章「The Essence of ML Type Inference」でも,HM(X) を具体的な制約システムの構成を踏まえて説明している.こちらは,HM 推論の説明から,HM(X) への拡張と具体的な制約システムの構成,ML の型推論実装に対する応用まで,ちゃんと各種形式化をしながら見ており,制約システムもかなり強力なものを構成している.こんな雑記事と違ってかなり参考になると思う (その分分量も多いが) ので,HM(X) に興味があればぜひ参照してみるのがいいんじゃないだろうか.</p>
<p>今回はこんな感じで.</p>
<table class="docutils footnote" frame="void" id="hmx-constraint-satisfiability" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[1]</a></td><td>なお,今回は分かりやすさと実装しやすさを優先し省略しているが,原文の規則では一般化で satisfiable という性質の導入を行い,制約含意でその性質が検証されるようにしている.この検証がない場合,絶対に満たされないような制約に対して一般化を行なってしまう可能性がある.個人的には別にそれでありだと思うし,制約の satisfiablity を考慮すると結構話がややこしくなるので今回はそこは検証しないようにしている.興味があれば題材の方を当たってもらうのが良いだろう.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="hmx-generalization" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[2]</a></td><td>HM(X) における本来の一般化は実はもう少し自由が与えられていて,型スキームに含める制約と環境に残す選択を分離できる.ただ,今回はアルゴリズムを単純にする為,そのような自由は許しておらず,全部の制約を型スキームに含めるようにしている.この辺は興味があれば題材の方をあたってもらうのが良いだろう.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="confluence-of-constraint-solving" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[3]</a></td><td>正規系を考えるとなると,気になるのは停止性と合流性が成り立つかだが,今回のシステムは停止性は成り立つが残念ながら合流性は成り立たない.ある程度書き換え結果は一貫したものになること,妥当でない制約を含む場合は必ず <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> に辿り着くことは保証できるが,完全に合流はせず書き換えによって最終的に得られる制約は変わる.そこら辺は実装依存ということになるだろう.合流性を保証する単純な方法は,書き換えシステムを決定的にすることだ.今回横着して,集合を使った書き換えを行なっているが,例えば原始制約の列に対して一番先頭から適用できる書き換え規則を適用していくというような規則を追加で入れれば,ある程度そこら辺の問題は解決できるだろう.今回は HM(X) の紹介という側面が強いのでそこまではやらず,とりあえず妥当な場合のみある程度一貫した結果が得られることだけで満足しておく.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2023/01/hmx-inference-with-constraints.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2023/01/hmx-inference-with-constraints.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Let多相と型推論2022-08-27T10:05:29+09:002022-08-27T10:05:29+09:00Mizunashi Manatag:mizunashi-mana.github.io,2022-08-27:/blog/posts/2022/08/hm-type-system/<p>プログラミング言語において,パラメータ多相は今や標準的な機能と言って良い.Java のジェネリクスや C++ のテンプレ …</p><p>プログラミング言語において,パラメータ多相は今や標準的な機能と言って良い.Java のジェネリクスや C++ のテンプレートをはじめ,Kotlin,Swift,TypeScript などの昨今の言語には当然搭載されており,Python の型アノテーションにもジェネリクスは搭載されている.パラメータ多相を搭載する言語では,パラメータを持たせたような型を付けた値を作成することができ,例えばリストの操作を,リストの要素の型についてはパラメータとして総称性を保ったまま,リストの構造だけに着目した関数として提供することができる.この機能は,プログラミングにおいて基本的なデータ構造を標準ライブラリが提供するために活用されることが多い.特にリストやマップなどのコンテナと呼ばれるデータ構造は,大体はそこまでカスタマイズ性を必要とせず,ある程度標準的な実装で需要を満足できる.そのため,パラメータ多相を使ってこれらのデータ構造とそれに対する操作を提供することで,快適なプログラミング体験を提供する言語が増えている.</p>
<p>さて,もう一つ,昨今標準的に搭載されるようになってきた型システム関連の機能として,型推論と呼ばれる機能がある.これは,文字通り型を自動で推論してくれる機能だ.基本的に型システムを持つ言語は,型によって値をある程度制約し,実行前にミスに気づけることを動機にしているものが多い.しかし,関数内の細かい変数などは自明に型が分かる場合も多く,一々型を書いていると冗長になりがちで,変更にも弱い.そこで最近はローカル変数について型推論機能を導入し,型を書いても書かなくても推論できる場合は推論して静的チェックを行なってくれる言語が増えている.</p>
<p>最近の主流な言語は,ほとんどこれら2つの機能を併せ持っている.ところが,実はある程度強力なパラメータ多相を実現できる機能では,型推論にある程度制約がかかってくることが知られている.今日は,それらの背景とパラメータ多相と型推論を同居させる際の指標となる著名なアイデア Let 多相とその型推論について紹介する.題材は以下.</p>
<blockquote>
Oukseh Lee and Kwangkeun Yi. Proofs about a folklore let-polymorphic type in-ference algorithm. ACM Transanctions on Programming Languages and Systems, 20(4):707–723, July 1998.</blockquote>
<p>なお,そもそもの提唱元はこの界隈では聖典となっている Milner 先生の以下の</p>
<blockquote>
Robin Milner. A theory of type polymorphism in programming. Journal of Computer and System Sciences, 17:348–375, 1978.</blockquote>
<p>だが,これより題材のやつの方が整理されているのでそっちをお勧めする.原典もちょっと難易度は高いが読んでみる価値はあると思うので,興味があればぜひ読んでみるのがいいんじゃないだろうか <a class="footnote-reference" href="#milner-paper" id="auto-id-1">[1]</a>.</p>
<div class="section" id="auto-id-2">
<h2>単純型付ラムダ計算と型推論<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Let多相の話に入る前に,まずは単純なものから話を始めていく.つまり,単純型付ラムダ計算の型推論を考えていく.単純型付ラムダ計算は,変数と定数,抽象,適用だけがある,単相な型の値しか作成できないような言語で,以下のような構文要素により構築される.</p>
<img alt="単純型付ラムダ計算の構文要素" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/simply-typed-lambda-syntax.png"/>
<p>今回は定数として, <tt class="docutils literal">unit</tt> 型の値 <tt class="docutils literal">()</tt> のみを考えることにする.型システムは以下のように与えられる.</p>
<img alt="単純型付ラムダ計算の型システム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/simply-typed-lambda-typing.png"/>
<p>型安全性とかは今回はあまり興味はないので,評価モデルとかは省略する.さて,この体系に関しての型推論というのはいくつか考えられるが,今回考えたい問題は,式の構文要素から型指定を抜いたものに対して型チェックを満足させるような型を計算できるかというものだ.つまり,以下の型なしラムダ計算の式に対して型がつけられる場合はその型を,付けられない場合付けられない旨を出力するアルゴリズムが作れるかということになる.</p>
<img alt="型なしラムダ計算の構文要素" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/untyped-lambda-syntax.png"/>
<p>ちゃんと問題として形式化するなら,</p>
<img alt="型なしラムダ計算の単純型推論による型システム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/simply-typed-inference-typing.png"/>
<p>のような型システムについて,</p>
<!-- -->
<blockquote>
型なしラムダ計算の項 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> に対して,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⊢</mo><mi>e</mi><mo>:</mo><mi>τ</mi></mrow><annotation encoding="application/x-tex">\vdash e: \tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> が存在すればその <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> を,存在しなければ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> を出力する</blockquote>
<p>アルゴリズムを構築できるかというのが今回扱う問題になる.これを解くためのアルゴリズムは色々知られているが,今回は以下のようなアルゴリズムを考える:</p>
<img alt="単純型付ラムダ計算の型推論" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-w-simply.png"/>
<p>この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="script">W</mi><mtext>simply</mtext></msub><mo stretchy="false">(</mo><mi mathvariant="normal">∅</mi><mo separator="true">,</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>S</mi><mo separator="true">,</mo><mi>τ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{W}_{\text{simply}}(\emptyset, e) = (S, \tau)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0822em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">simply</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">∅</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">)</span></span></span></span></span> の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">d</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">f</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">t</mi></mrow><mo stretchy="false">(</mo><mi>τ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathbf{default}(\tau)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathbf">default</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">)</span></span></span></span></span>,それ以外の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> を返すと問題の解になる.アルゴリズム中での <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">U</mi></mrow><annotation encoding="application/x-tex">\mathcal{U}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathcal" style="margin-right:0.09931em;">U</span></span></span></span></span> は単一化と呼ばれるアルゴリズムで,以下を返す:</p>
<!-- -->
<blockquote>
<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi><msub><mi>τ</mi><mn>1</mn></msub><mo>=</mo><mi>S</mi><msub><mi>τ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">S\tau_1 = S\tau_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を満たす置換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi></mrow><annotation encoding="application/x-tex">S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span> がある時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">U</mi><mo stretchy="false">(</mo><msub><mi>τ</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>τ</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">\mathcal{U}(\tau_1, \tau_2) = S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal" style="margin-right:0.09931em;">U</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span></blockquote>
<p>アルゴリズム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="script">W</mi><mtext>simply</mtext></msub></mrow><annotation encoding="application/x-tex">\mathcal{W}_{\text{simply}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0822em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">simply</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> は基本抽象の変数の型を変数としておいておき,単一化により型チェックが通る範囲まで型を具体化する.例えば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>λ</mi><mi>f</mi><mo separator="true">.</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>λ</mi><mi>y</mi><mo separator="true">.</mo><mi>f</mi><mtext> </mtext><mi>y</mi><mo stretchy="false">)</mo><mtext> </mtext><mo stretchy="false">(</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>x</mi><mo stretchy="false">)</mo><mtext> </mtext><mtext mathvariant="monospace">()</mtext></mrow><annotation encoding="application/x-tex">(\lambda f\ldotp \lambda x\ldotp \lambda y\ldotp f\; y)\; (\lambda x\ldotp x)\;\text{\texttt{()}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">λ</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord text"><span class="mord texttt">()</span></span></span></span></span></span></span> に対して,この推論アルゴリズムは次のように動く:</p>
<img alt="単純型付ラムダ計算の型推論の導出例" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-w-simply-deriv-example.png"/>
<p>イメージとしては,以下のような感じ:</p>
<img alt="単純型付ラムダ計算の型推論ステップ例" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-w-simply-deriv-example-steps.png"/>
<p>抽象の各変数に型変数を割り当てていき,各式を見て単一化により型を具体化していく.このようにして,単純型付ラムダ計算の型推論は行える.</p>
</div>
<div class="section" id="auto-id-3">
<h2>Let多相<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,先ほど見た単純型付きラムダ計算は単相的な型,つまりパラメータなどを持たない型としか扱えない.なので,例えば次のようなプログラムは型付けできない:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mrow><mi>i</mi><mi>d</mi></mrow><mo separator="true">.</mo><mo stretchy="false">(</mo><mrow><mi>i</mi><mi>d</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mtext> </mtext><mo stretchy="false">(</mo><mrow><mi>i</mi><mi>d</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">()</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\lambda \mathit{id}\ldotp (\mathit{id}\;(\lambda x\ldotp x))\;(\mathit{id}\;\text{\texttt{()}})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">λ</span><span class="mord"><span class="mord mathit">id</span></span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord text"><span class="mord texttt">()</span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>先ほど紹介した型推論アルゴリズムでこのプログラムの型を推論しようとすると,</p>
<img alt="単純型付ラムダ計算の型推論で一部単一化に失敗する" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-w-simply-failed-poly-example.png"/>
<p>のように途中で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msub><mi>β</mi><mn>2</mn></msub><mo>→</mo><msub><mi>β</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>→</mo><msub><mi>β</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">(\beta_2 \to \beta_2) \to \beta_3</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">u</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">t</mi></mrow><mo>→</mo><msub><mi>β</mi><mn>4</mn></msub></mrow><annotation encoding="application/x-tex">\mathbf{unit} \to \beta_4</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">unit</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> のような型を単一化しようとして失敗する.これは,変数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">\mathit{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">id</span></span></span></span></span></span> を関数に適用する箇所と,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">u</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{unit}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">unit</span></span></span></span></span></span> 型の値に適用する箇所の二つがあるためだ.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">\mathit{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">id</span></span></span></span></span></span> を関数をとる関数型として扱うと後者が立たず,逆に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">u</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{unit}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">unit</span></span></span></span></span></span> 型の値をとる関数型として扱うと前者が立たない.これが単一化の失敗に現れており,この式に正当な型をつけることはできない.これを回避するには,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><msub><mrow><mi>i</mi><mi>d</mi></mrow><mn>1</mn></msub><mo separator="true">.</mo><mi>λ</mi><msub><mrow><mi>i</mi><mi>d</mi></mrow><mn>2</mn></msub><mo separator="true">.</mo><mo stretchy="false">(</mo><msub><mrow><mi>i</mi><mi>d</mi></mrow><mn>1</mn></msub><mtext> </mtext><mo stretchy="false">(</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mtext> </mtext><mo stretchy="false">(</mo><msub><mrow><mi>i</mi><mi>d</mi></mrow><mn>2</mn></msub><mtext> </mtext><mtext mathvariant="monospace">()</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\lambda \mathit{id}_1\ldotp \lambda \mathit{id}_2\ldotp (\mathit{id}_1\;(\lambda x\ldotp x))\;(\mathit{id}_2\;\text{\texttt{()}})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">λ</span><span class="mord"><span class="mord"><span class="mord mathit">id</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">λ</span><span class="mord"><span class="mord"><span class="mord mathit">id</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathit">id</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathit">id</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord text"><span class="mord texttt">()</span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>のようにそれぞれ必要な型ごとに変数を用意する必要がある.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">\mathit{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">id</span></span></span></span></span></span> の実装としては <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">\lambda x\ldotp x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span></span></span></span></span> が関数を受け取る場合も <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">u</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{unit}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">unit</span></span></span></span></span></span> を受け取る場合も適合する.しかし,単純型付ラムダ計算の世界ではこの実装も型によってそれぞれ書く必要がある.しかし,これはモジュール性の観点からも再利用性の観点からも微妙だ.</p>
<p>そこで,多くのプログラミング言語は多相型を持つ値を作れるようにすることである程度この問題を解決している.具体的には,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mrow><mi>i</mi><mi>d</mi></mrow><mo>:</mo><mi mathvariant="normal">∀</mi><mi>α</mi><mo separator="true">.</mo><mi>α</mi><mo>→</mo><mi>α</mi><mo>=</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>x</mi><mtext> </mtext><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mi>i</mi><mi>d</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mi>λ</mi><mi>x</mi><mo separator="true">.</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mtext> </mtext><mo stretchy="false">(</mo><mrow><mi>i</mi><mi>d</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">()</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\mathbf{let}\;\mathit{id}: \forall \alpha\ldotp \alpha \to \alpha = \lambda x\ldotp x\; \mathbf{in}\; (\mathit{id}\;(\lambda x\ldotp x))\;(\mathit{id}\;\text{\texttt{()}})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">let</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">in</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mord mathnormal">λ</span><span class="mord mathnormal">x</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord text"><span class="mord texttt">()</span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>のように書くと,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">\mathit{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">id</span></span></span></span></span></span> は関数を受け取る部分では <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> を適合する関数型に,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext mathvariant="monospace">()</mtext></mrow><annotation encoding="application/x-tex">\text{\texttt{()}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord text"><span class="mord texttt">()</span></span></span></span></span></span></span> を受け取る部分では <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mrow><mi mathvariant="bold">u</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">t</mi></mrow></mrow><annotation encoding="application/x-tex">\alpha = \mathbf{unit}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">unit</span></span></span></span></span></span> にと,それぞれの使用箇所で適合する型をパラメータに入れて,それで型付できればよしとするようなシステムを搭載している.これにより,多相型を持つ値を作ってそれを公開するようにすれば,使用箇所でわざわざ実装を書き直すことなく型を変えて使用することができ,実装と使用箇所を分離して管理することができるようになる.</p>
<p>さて,表現力の観点からも多相型を入れた体系は理論的に幾つか提唱されており,特に単純型付ラムダ計算にパラメータ多相を入れた拡張として System F という体系がある.System F は多相型の値を単装型の値と同じように扱うことができ,かなり強力な拡張になる.ただ,System F は完全な型推論が不可能であることが知られている <a class="footnote-reference" href="#system-f-typability" id="auto-id-4">[2]</a>.現実的には,プログラミング言語の機能として,System F ほどの強力な拡張はいらずある程度型推論ができる体系が欲しくなる場合が多い.そこで,多相型の値の作成方法と扱い方を単装型に比べて制限した上で,完全な型推論が行える体系として Let 多相というものが提唱されている.Let 多相は先ほどの単純型付ラムダ計算の構文に,let 構文と呼ばれるものを足す.構文の全体は以下のようになる:</p>
<img alt="Let 多相の構文" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/letpoly-syntax.png"/>
<p>let 構文は,多相型を持つ値を作成できる構文で,この構文で束縛された変数のみ多相型を持って良いということになる.Let 多相では型は単相型と多相型の二種類を持ち,それぞれ以下のような構文を持つ:</p>
<img alt="Let 多相の型の構文" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/letpoly-type-syntax.png"/>
<p>単相型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> は基本単純型付ラムダ計算の時と変わらないが,変数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> が許容される点が異なる.ただし,変数を含んでいても式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> では変数に関数型を,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> では変数に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">u</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{unit}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">unit</span></span></span></span></span></span> 型をというような使い分けはできず,変数には何か一つの型を固定して単相的に紐づけることしかできない.逆に,多相型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> は内部にパラメータを持ち,そのパラメータに応じて単相型を変えることができる.Let 多相の型付規則は以下のようになる:</p>
<img alt="Let 多相の型システム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/letpoly-type-system.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi><mo>≻</mo><mi>τ</mi></mrow><annotation encoding="application/x-tex">\sigma \succ \tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≻</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> はインスタンス化と呼ばれ,多相型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> のパラメータに何かしら単相型を紐づけたものが <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> であると読む.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">G</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">n</mi></mrow><mo stretchy="false">(</mo><mi mathvariant="normal">Γ</mi><mo separator="true">,</mo><mi>τ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{Gen}(\Gamma, \tau)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">Gen</span></span><span class="mopen">(</span><span class="mord">Γ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">)</span></span></span></span></span> は一般化と呼ばれ,単相型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> に含まれる変数をパラメータ化して多相型を返す操作になる.Let 多相は,環境に多相型を持つ変数を含む.しかし,その変数が式中で使われる場合はインスタンス化して使わなければいけないというのが変数の規則になる.抽象と適用は単純型付ラムダ計算の際と同じで,抽象の際環境に入る変数は,パラメータのない多相型として追加される.let 構文では,変数に束縛する式の型を一般化して,型が具体化されていない部分はパラメータとして扱って良いということを示している.Let 多相の型推論とは,この型システムに対して,</p>
<!-- -->
<blockquote>
Let 多相の項 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> に対して,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⊢</mo><mi>e</mi><mo>:</mo><mi>τ</mi></mrow><annotation encoding="application/x-tex">\vdash e: \tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> が存在すればその <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>τ</mi></mrow><annotation encoding="application/x-tex">\tau</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span></span></span></span></span> を,存在しなければ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> を出力する</blockquote>
<p>アルゴリズムを構築できるかという問題になる.</p>
</div>
<div class="section" id="auto-id-5">
<h2>Let 多相の型推論<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>この型推論アルゴリズムは,単純型付ラムダ計算の時に紹介したアルゴリズムを let 構文に対して拡張することで得られる:</p>
<img alt="Algorithm W" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-w.png"/>
<p>この時式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">W</mi><mo stretchy="false">(</mo><mi mathvariant="normal">∅</mi><mo separator="true">,</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>S</mi><mo separator="true">,</mo><mi>τ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{W}(\emptyset, e) = (S, \tau)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal" style="margin-right:0.08222em;">W</span><span class="mopen">(</span><span class="mord">∅</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">)</span></span></span></span></span> の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">d</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">f</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">t</mi></mrow><mo stretchy="false">(</mo><mi>τ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathbf{default}(\tau)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathbf">default</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">)</span></span></span></span></span>,それ以外の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> を返せば,型推論アルゴリズムとなる.単純型付ラムダ計算の時と異なるのは,インスタンス化と一般化の部分,すなわち変数の規則と let 構文の規則で,その他は基本単純型付きラムダ計算の時と同じである.考え方も基本同じで,ただ多相型から変数が参照される際にインスタンス化されること,let 構文では一般化が起きることが起きるようになることが付加されるという感じだ.</p>
<p>導出例は以下のようになる:</p>
<img alt="Algorithm W での推論例" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-w-deriv-example.png"/>
<p>イメージとしてはこんな感じ:</p>
<img alt="Algorithm W での推論ステップ例" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-w-deriv-example-steps.png"/>
<p>変数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">\mathit{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">id</span></span></span></span></span></span> に行き着いたところどころで,インスタンス化によって新たに変数が置かれるのがポイントだ.これにより,同じ変数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">\mathit{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">id</span></span></span></span></span></span> でも出現位置が異なると異なる型を持てるようになる.</p>
<p>なお,Milner 先生の元文献では Algorithm J という Algorithm W の再代入可能な変数を使った効率良い版の実装も紹介されているので,興味がある人は見てみると実装の参考になるかもしれない.</p>
<p>さて,一応題材として扱ったやつにも触れておくと,今回の題材では Algorithm W とは別に Algorithm M という別の let 多相の推論アルゴリズムを考案している.Algorithm W は適宜型が分からない部分で変数を導入し推論を進め,部分式についての型の情報が揃った段階で単一化することで型の具体化と競合がないかのチェックを行なっていた.しかし,この方式は,型エラーが単一化まで先延ばしにされ,分かりにくいという問題がある.Algorithm M はその問題を解消するため,最後に一気に単一化を行うのではなく,ある程度できる単一化を早期に徐々に進めていこうといった感じの型推論アルゴリズムになる.具体的には以下のようになる:</p>
<img alt="Algorithm M" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-m.png"/>
<p>この時,式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">M</mi><mo stretchy="false">(</mo><mi mathvariant="normal">∅</mi><mo separator="true">,</mo><mi>e</mi><mo separator="true">,</mo><mi>β</mi><mo stretchy="false">)</mo><mo>=</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">\mathcal{M}(\emptyset, e, \beta) = S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal">M</span><span class="mopen">(</span><span class="mord">∅</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span> の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">d</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">f</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">t</mi></mrow><mo stretchy="false">(</mo><mi>S</mi><mi>β</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathbf{default}(S\beta)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathbf">default</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05278em;">Sβ</span><span class="mclose">)</span></span></span></span></span>,それ以外の時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> を返せば,型推論アルゴリズムとなる.基本的には,与えられた式の型を変数としておき,それを部分式について推論を進める途中節々で単一化をかけて,徐々に具体化していくという感じだ.導出例は以下のようになる:</p>
<img alt="Algorithm M による推論導出例" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/algorithm-m-deriv-example.png"/>
<p>正直どっちがいいかは場合による気がするが,まあこういうアルゴリズムもあるよという感じだ.こんな感じで Let 多相であれば完全なアルゴリズムを与えられる.正当性とかに興味があれば,題材と Milner 先生の方のを見てみると良いだろう.</p>
</div>
<div class="section" id="auto-id-6">
<h2>単一化の実装<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,ここまで Let 多相の推論について扱ってきたが,推論アルゴリズムは基本単一化というアルゴリズムを基に構築されており,重要なパーツになっている.最後にこの単一化の部分について少し触れておこう.単一化は何も型の文脈だけで重要なアルゴリズムではなく,論理プログラミング,パターンマッチなどでも根幹をなす概念で,要は変数を含む項が2つあった時,その変数の部分いい感じに弄れば同じにできるかというのを解くアルゴリズムだ.ただ,体系によって結構決定不能になったり,効率があまり良くできないといった問題があるので注意が必要な問題でもある.</p>
<p>さて,今回扱う範囲の単一化は,俗に first-order unification と呼ばれる問題の範疇になる.要は単純な木で表現できる,変数とコンストラクタで構成される項の単一化は大体どういう構文を持っていても似たようなアルゴリズムが用意できるということだ.ついでに,higher-order,つまりラムダ項などを入れ正規化後の項が一致するかみたいな問題は決定不能になることが知られている.つまりは,型システムに型関数みたいなもの入れた状態で,Algorithm W のような型推論入れようとすると基本決定不能になる.なので,今回は first-order unification の範囲なので,アルゴリズムはいくつか知られたものがあるが,現実的には型システム強化しすぎると一筋縄でいかなくなるので注意が必要という感じ.</p>
<p>first-order unification のアルゴリズムはいくつか知られているが,中でも Martelli-Montanari Algorithm <a class="footnote-reference" href="#mm-fo-unification" id="auto-id-7">[3]</a> が有名なものかな <a class="footnote-reference" href="#about-unification-problem" id="auto-id-8">[4]</a>.基本的には以下のようなアルゴリズム:</p>
<img alt="Martelli-Montanari Algorithm" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/08/hm-type-system/hm-type-system/mm-unification.png"/>
<p>単純に項の根から一致しているか見ていって,変数部分は代入で両者一致するよう置き換えていきましょうというやつ.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>τ</mi><mn>1</mn></msub><mo>→</mo><msub><mi>τ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">\tau_1 \to \tau_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を2引数のコンストラクタ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mo>→</mo><mo stretchy="false">)</mo><mo stretchy="false">(</mo><msub><mi>τ</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>τ</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(\to)(\tau_1, \tau_2)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mrel">→</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext mathvariant="monospace">()</mtext></mrow><annotation encoding="application/x-tex">\text{\texttt{()}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord text"><span class="mord texttt">()</span></span></span></span></span></span></span> を0引数のコンストラクタだと思ってこのアルゴリズムを使うと,単一化ができる.</p>
</div>
<div class="section" id="auto-id-9">
<h2>まとめ<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,Let 多相とその推論アルゴリズムの紹介だった.あんまりネット上でこういうのまとめてる文献見つからなかったので,自分の参照用という側面が強いが,まあなんかお役に立てばという感じ.</p>
<p>型付ラムダ計算ベースの多相型を導入している言語は,それぞれが色々創意工夫をしてはいるものの,基本はこれらのアルゴリズムをベースにしていることが多い.なので,ここら辺理解しておくとエラーメッセージの気持ちを読み取りやすくなったりする <a class="footnote-reference" href="#type-error-is-not-useful" id="auto-id-10">[5]</a>.興味があれば学んでみて損はないだろう.</p>
<p>今回はこんな感じで.</p>
<table class="docutils footnote" frame="void" id="milner-paper" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td>正当性とか諸々をすっ飛ばせば,Algorithm W,Algorithm J とかの部分は普通に理解できるだろうし.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="system-f-typability" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[2]</a></td><td>J.B.Wells. Typability and typechecking in system f are equivalent and undecidable. Annals of Pure and Applied Logic, 98:111–156, 6 1999.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="mm-fo-unification" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[3]</a></td><td>Alberto Martelli and Ugo Montanari. An efficient unification algorithm. ACM Transactions on Programming Languages and Systems, 4:258–282, 4 1982.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="about-unification-problem" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-8">[4]</a></td><td>ここら辺はあんまり知らん領域なので良く分からん.SAT へのエンコード方法とかあったりするんかな?</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="type-error-is-not-useful" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-10">[5]</a></td><td>正直アルゴリズム理解しないと読み取れない型エラーもどうかと思うが...</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2022/08/hm-type-system.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2022/08/hm-type-system.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>文脈依存 PEG による Haskell パーサ2022-02-23T14:53:35+09:002022-02-23T14:53:35+09:00Mizunashi Manatag:mizunashi-mana.github.io,2022-02-23:/blog/posts/2022/02/contextual-peg-parser/<p>前に PEG パーサジェネレータライブラリ ptera を作っているという話をしたが,今回はその第二弾.ptera で Haskell2010 の文法パーサを …</p><p>前に PEG パーサジェネレータライブラリ ptera を作っているという話をしたが,今回はその第二弾.ptera で Haskell2010 の文法パーサを例に追加してみたんだが,その過程で色々あったのでその備忘録.</p>
<p>結論から言うと,ptera に前回から以下の拡張を加えた.</p>
<ul class="simple">
<li>先読みを強化し,もうちょっとちゃんと機能するように</li>
<li>文脈依存でパースができるようにした</li>
</ul>
<p>後は,Template Haskell で文法書けるようにしたりもしたが,まあそれはいいでしょ.</p>
<div class="section" id="haskell2010-ptera">
<h2>Haskell2010 と ptera<a class="headerlink" href="#haskell2010-ptera" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ptera でひとまず Template Haskell で文法が書けるフロントエンド部分作った後,Haskell 2010 ぐらいパースできないと使い物にならないなあと言う感じで Haskell の example project 書いてみたんだが,ここで色々つまづいてしまった.主に今回説明する ptera の拡張は,この example project 書くために入れたと言っても過言ではない.まあ,普通に Haskell 2010 パーサ実装以外でも役に立つ機能で,今後僕は普通に使っていく機能ではあると思うので足りない機能ではあったんだろうけど.</p>
<p>さて, <a class="reference external" href="https://www.haskell.org/onlinereport/haskell2010/haskellch10.html#x17-18000010.5">Haskell 2010 の文法</a> 自体はまあ大きくはあるんだが,曖昧さ含む部分が結構あるのを除けば割と普通の文脈自由文法によって定義されていると思う <a class="footnote-reference" href="#qualified-tokens" id="auto-id-1">[1]</a>.ただ,Haskell 2010 のパーサを実装する上で凶悪なものとして知られているのが,レイアウトルールと呼ばれる規則だ.</p>
<p>レイアウトルールとはインデントによって文法の意味を変えるようなパース時のメタ規則だ <a class="footnote-reference" href="#haskell-layout-rule" id="auto-id-2">[2]</a>.レイアウトルールは Haskell 内の用語で,一般的にはオフサイドルールなどと呼ばれることもある.仕様自体は一見そこまで複雑なものではなく,基本的にはトークナイズの後にそれぞれのトークンの位置を見て「 <tt class="docutils literal">{</tt>」,「 <tt class="docutils literal">;</tt>」,「 <tt class="docutils literal">}</tt>」を自動で挿入するようなものになっている.これを前段にかます前提で文脈自由文法は定義されていて,例えば</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">1</span>
</pre></div></td></tr></table></div>
<p>みたいなプログラムは,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">{</span><span class="n">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="p">;</span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">{</span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">1</span>
<span class="p">}}</span>
</pre></div></td></tr></table></div>
<p>のように明示的にレイアウトが判別できるようなプログラムに変換された後,パースが走るという感じだ.さて,この話を聞く限りはそこまで複雑な話であるように見えないだろう.実際,ここまでの話で終わるならレイアウト・ルールがここまでパーサ実装者にとって凶悪認定されることはないだろう.パーサ実装者の頭を悩ますのは,レイアウトルールの規則の中の1つ, <a class="reference external" href="https://www.haskell.org/onlinereport/haskell2010/haskellch10.html#x17-17800010.3">Haskell 2010 Language Report 10.3 Layout</a> に存在する以下の規則だ:</p>
<blockquote>
<p>L (t : ts) (m : ms) = } : (L (t : ts) ms) if m ≠ 0 and parse-error(t) (Note 5)</p>
<p>Note 5.
The side condition parse-error(t) is to be interpreted as follows: if the tokens generated so far by L together with the next token t represent an invalid prefix of the Haskell grammar, and the tokens generated so far by L followed by the token "}" represent a valid prefix of the Haskell grammar, then parse-error(t) is true.</p>
<p>Note 5.
右隅の条件 parse-error(t) は次のように解釈されます: L がこれまで生成したトークンと次のトークン t が,Haskell 文法の無効な接頭辞を成し,L がこれまで生成したトークンと "}" が Haskell 文法の有効な接頭辞を成す場合,parse-error(t) は真である.</p>
</blockquote>
<p><tt class="docutils literal">L</tt> は文法に入る前の前処理で,トークンの位置を見ていい感じに「 <tt class="docutils literal">{</tt>」,「 <tt class="docutils literal">;</tt>」,「 <tt class="docutils literal">}</tt>」を挿入する前処理関数の実装になっている.この規則以外はトークンとその位置から決まるのだが,この規則だけはなんと文法のパースができるかに依存することになる.この関数を愚直に実装するなら,トークン列の全ての位置でパースしてみて失敗しないかを見ることになるだろう.さらに厄介なのが,パースが失敗した後に「 <tt class="docutils literal">}</tt>」が挿入されトークン列が <strong>変わる</strong> ということだ.そのため,今まで試してきたパースとトークンが挿入された後では結果が異なる可能性が十分あり,予測も難しいということになる.</p>
<p>我らが GHC も例に漏れずレイアウトルールの実装ではかなり苦労しており,時々パーサに関するイシューが上がっている <a class="footnote-reference" href="#ghc-layout-maintenance-cost" id="auto-id-3">[3]</a>.また,Haskell のパーサは GHC 以外でも Haskell コミュニティ内でさえいくつも実装が行われている.HSE (haskell-src-exts) と言うライブラリもその1つで <tt class="docutils literal">Hoogle</tt>, <tt class="docutils literal"><span class="pre">stylish-haskell</span></tt> などで使われている.HSE ももちろんレイアウトルールには対応しているわけだが,その実装にもかなり根深い問題として,空の <tt class="docutils literal">where</tt> をパースできないと言うことが知られている <a class="footnote-reference" href="#hse-empty-where-issue" id="auto-id-4">[4]</a>.</p>
<p>このような苦労をしてまでこのレイアウトルールを入れることに意味はあるのだろうか? このルールさえなければ,おそらく GHC や他の実装もトークナイザとパーサを完全に切り離して実装できるはずだ.このルールが役に立つ例として,例えば以下のケースがある:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
</pre></div></td></tr></table></div>
<p>この場合,詳細は省くが</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">{</span><span class="n">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">{</span><span class="n">pure</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="p">;}</span><span class="kr">where</span>
<span class="w"> </span><span class="p">{</span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span><span class="p">}}</span>
</pre></div></td></tr></table></div>
<p>のような形でトークンが挿入されることになる.このうち, <tt class="docutils literal">where</tt> の手前の <tt class="docutils literal">}</tt> がパースエラーによって挿入されるものになる.このようなプログラムはしばしば書かれるので,割とパースエラーによるレイアウトに依存したプログラムはあるはずだ.後は,Haskell Language Report でも例として紹介されている以下のケースだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">e</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="n">e'</span>
</pre></div></td></tr></table></div>
<p>この場合は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">let</span><span class="w"> </span><span class="p">{</span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">e</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">}</span><span class="kr">in</span><span class="w"> </span><span class="n">e'</span>
</pre></div></td></tr></table></div>
<p>のようにトークンが挿入されることになる.流石にこういうプログラムを書く人は少ないかもしれないが, <tt class="docutils literal">let x = 1 in x + 1</tt> みたいなワンライナーを書く人は割といるんじゃないだろうか.このようなプログラムはパースエラーによるレイアウト終了のルールに頼っていることになる.割と便利ではあるのだ.正しく実装するのが非常に困難なだけで.</p>
<p>さて,具体的にこのレイアウトルールに則ったパースをどう行うかだが,GHC ではどうやっているかというと,GHC が使っている LALR パーサジェネレータに,error トークンというそのトークンの位置でパースが失敗した場合に復帰するようなうってつけの機能が実装されており,それを使用している.GHC の場合は,そもそもトークナイザとパーサが分かれてはいるものの深く連動しており,互いにコンテキストを共有しあっているという (恐ろしい) 実装になっていて <a class="footnote-reference" href="#other-implemententation-layout-rule" id="auto-id-5">[5]</a>,かなり改修が困難なものになっている.そのため,昔はコーナケースのパースイシューを提示されても修正が不可能みたいなこともあり (今も眠っているイシューがあるかもしれない),バージョンアップ毎のリファクタリングでかろうじて拾っていくみたいな状況になっている.</p>
<p>例に漏れず ptera でもレイアウトルールに対応するため大幅な機能アップデートを余儀なくされた.特に,パース途中で入力のトークン列が変わるというのは,PEG と大変相性が悪い.最終的にその部分については,それなりに満足いく対応はできたが,代わりに幾つかのものを捨てることにもなった.その対応方法について紹介すると言うのが,今回の内容だ.対応方針は「パースアクションで文脈を変更できるようにし,その際のメモ化は捨てる」だ.この結果,純粋な (アクションで文脈をいじらない) PEG が入力なら相変わらず線形時間でパース可能だが,全体としては ptera は線形時間パースを捨てるという道を選んだ.</p>
</div>
<div class="section" id="peg">
<h2>文脈依存 PEG とレイアウトルール<a class="headerlink" href="#peg" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,ptera で Haskell のパーサを実装するとなった段階でまず着手したことは,そもそもトークン列をパースの状態によって変えるのをやめられないかということだった.入力トークン列がパース途中に変わる場合かなり実装が手間だし,そもそも PEG とかなり相性が悪い.ただ,まあこんぐらいパースできないと後々困るので,方法をいくつか模索した.その結果,PEG ではちょっと難しそうだったので,文法を拡張する方向でいくことにした.ただ拡張の方向として,文法に何か規則を加えたわけでなく,文脈依存のアクションを許すようにした.具体的には,文脈を規則毎に更新したり,文脈によってパースを失敗させたりできる.</p>
<p>コンセプトとしては,</p>
<pre class="literal-block">
body ::= open body? close
open ::= "(" | "{" | "["
close ::= ")" | "}" | "]"
</pre>
<p>みたいな文法があった時に,</p>
<pre class="literal-block">
body ::= open body? close
open ::= "(" { l ↦ push("(",l) }
| "{" { l ↦ push("{",l) }
| "[" { l ↦ push("[",l) }
close ::= ")" { l ↦ pop(l) | !empty(l) & front(l) = "(" }
| "}" { l ↦ pop(l) | !empty(l) & front(l) = "{" }
| "]" { l ↦ pop(l) | !empty(l) & front(l) = "[" }
</pre>
<p>みたいな形で文脈の変更アクションと文脈検査を追加できるみたいな感じ.読み方としては,<tt class="docutils literal">{}</tt> で囲まれた部分が文脈操作を現していて,<tt class="docutils literal">x ↦ y</tt> で文脈 <tt class="docutils literal">x</tt> を <tt class="docutils literal">y</tt> に更新する. <tt class="docutils literal">|</tt> で条件をつけることもでき,その場合条件が成立しなければその部分の選択を失敗させ,次の選択にいく.最初に例示した文脈なしの場合は開く数と閉じる数が一緒かどうかを検査しないので,例えば <tt class="docutils literal"><span class="pre">([{])}</span></tt> みたいな対応がめちゃくちゃなものを accept してしまう.しかし文脈付きのやつはその対応を文脈上で検査することで,ちゃんと括弧の種類が対応しているものでないと accept しない.もちろんこの例は,次のように書けば文脈上での検査は不要になる:</p>
<pre class="literal-block">
body ::= "(" body? ")"
| "[" body? "]"
| "{" body? "}"
</pre>
<p>ただ,これぐらいの構文定義ならいいかもしれないが,構文定義が大きくなると文脈でなんとかした方が見通しが良くなることもある.もちろんこの機能は,文法クラスの拡張にも使える.基本 PEG はスタック1つ分のマシンで検査できる範囲としたら,文脈にもスタックを持たせることでスタック2つ分の検査ができる.なので文脈の持たせ方によっては,基本チューリング完全な構文検査ができる.</p>
<p>この機能をどうレイアウトルールに適用するかだが,基本的な発想としては,レイアウトルールの前処理関数を文脈操作でエミュレートすると言う感じになる.さて,その前にまず Haskell のレイアウトルールの詳細について説明しておこう.Haskell Language Report に記載されているレイアウトルール <a class="footnote-reference" href="#haskell-layout-rule" id="auto-id-6">[2]</a> の処理は,2段階に分けられる.</p>
<ol class="arabic simple">
<li>1段階目はトークンの位置情報を適度に挿入する処理になる.</li>
<li>2段階目がその位置情報を見ながらレイアウトトークン「 <tt class="docutils literal">{</tt>」,「 <tt class="docutils literal">;</tt>」,「 <tt class="docutils literal">}</tt>」を挿入していく.</li>
</ol>
<p>具体的には次のとおりだ.1段階目は,トークンの列に対して要所要所に以下のレイアウト位置情報を埋め込む:</p>
<dl class="docutils">
<dt><tt class="docutils literal">{n}</tt></dt>
<dd>新規レイアウト開始. <tt class="docutils literal">n</tt> はレイアウトのインデント位置を表す.</dd>
<dt><tt class="docutils literal"><n></tt></dt>
<dd>レイアウト中の改行. <tt class="docutils literal">n</tt> は改行時のインデント位置を表す.</dd>
</dl>
<p>処理の内容は以下のようになる:</p>
<img alt="1段目のレイアウト処理" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/02/contextual-peg-parser/contextual-peg-parser/layout-preprocess-1.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> はトークンの列 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>t</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{ts}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord"><span class="mord mathit">ts</span></span></span></span></span></span> を受け取り,適宜レイアウト位置情報を挿入する.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">module</span><span class="w"> </span><span class="nn">Main</span><span class="w"> </span><span class="kr">where</span>
<span class="nf">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="s">"str"</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s">"str"</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Nothing</span>
<span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">z</span>
<span class="nf">f</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="kr">where</span>
</pre></div></td></tr></table></div>
<p>のようなプログラムの場合,</p>
<pre class="literal-block">
module Main where
{1} x = case "str" == "str" of
{5} True -> Nothing
<5> False -> y where
{9} y = do {16} z <- Just ()
<16> pure z
<1> f z = z where{0}
</pre>
<p>のようになる.新規レイアウト開始情報は,</p>
<ul class="simple">
<li>プログラムが <tt class="docutils literal">module</tt> で始まってない場合一番最初</li>
<li><tt class="docutils literal">let</tt>, <tt class="docutils literal">where</tt>, <tt class="docutils literal">do</tt>, <tt class="docutils literal">of</tt> の4つのトークンの後</li>
</ul>
<p>で <tt class="docutils literal">{</tt> が続いていない場合に挿入される.Haskeller の中にはあまり意識していない人も多いかもしれないが,プログラム全体もレイアウトを持っているので,例えば</p>
<pre class="literal-block">
x = 0
y = 1
</pre>
<p>のようなプログラムは</p>
<pre class="literal-block">
{x = 0
}y = 1
</pre>
<p>のようにレイアウトがちゃんと付かないためパースが失敗する.このような場合に最初に <tt class="docutils literal">{</tt> が挿入されるのは, <tt class="docutils literal">P</tt> が挿入した新規レイアウト開始の情報に依るものだ.<tt class="docutils literal">module</tt> が最初にない場合となっているのは, <tt class="docutils literal">module ... where</tt> の後でもレイアウトを字下げなしで開始できるようにするためのハックだ.詳しくは後述するが,Haskell のレイアウトは今のレイアウトより 1 以上字下げをしないと開始できない.なので,もし「<tt class="docutils literal">module</tt> が最初にない場合」の条件がなければ,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">module</span><span class="w"> </span><span class="nn">Main</span><span class="w"> </span><span class="kr">where</span>
<span class="nf">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
</pre></div></td></tr></table></div>
<p>みたいなプログラムは valid にならず,代わりに必ず</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">module</span><span class="w"> </span><span class="nn">Main</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
</pre></div></td></tr></table></div>
<p>のように一文字以上下げてモジュールの本体を書かなければいけなくなる.そこらへんの事情があって,最初だけ特殊な条件が入れてある.</p>
<p>2段目のレイアウト処理では,1段目に挿入されたレイアウト情報とスタックを元に,レイアウトトークンを挿入していく:</p>
<img alt="2段目のレイアウト処理" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/02/contextual-peg-parser/contextual-peg-parser/layout-preprocess-2.png"/>
<p>この処理により,最終的に上記で挙げたプログラム</p>
<pre class="literal-block">
module Main where
{1} x = case "str" == "str" of
{5} True -> Nothing
<5> False -> y where
{9} y = do {16} z <- Just ()
<16> pure z
<1> f z = z where {0}
</pre>
<p>は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">module</span><span class="w"> </span><span class="nn">Main</span><span class="w"> </span><span class="kr">where</span>
<span class="p">{</span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="s">"str"</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s">"str"</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="p">{</span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Nothing</span>
<span class="w"> </span><span class="p">;</span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">{</span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="p">{</span><span class="n">z</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="p">;</span><span class="n">pure</span><span class="w"> </span><span class="n">z</span>
<span class="p">}}};</span><span class="n">f</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="kr">where</span><span class="p">{}}</span>
</pre></div></td></tr></table></div>
<p>のように明示的なレイアウトトークンが挿入された状態に変換される.この処理は大まかには</p>
<ul class="simple">
<li>レイアウト開始時スタックにレイアウト開始位置をプッシュする.明示的な中括弧の場合は <tt class="docutils literal">0</tt> をプッシュする</li>
<li>暗黙的な中括弧で開始されたレイアウトについては,スタックとレイアウト位置情報によって適宜レイアウトを閉じ,スタックから対応するレイアウト開始位置をポップする.明示的な中括弧閉じの場合は,スタックの先頭が <tt class="docutils literal">0</tt> かチェックしてポップする</li>
</ul>
<p>と言う感じのことをする.細かく見ていくと,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mtext mathvariant="monospace">";"</mtext><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mo stretchy="false">⟨</mo><mi>n</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>n</mi><mo>:</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = \texttt{";"}:L_1(\mathit{ts}, \mathit{ms})\hspace{1em} (t = \langle n\rangle, \mathit{ms} = n:\mathit{ms}')
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1389em;"></span><span class="mord text"><span class="mord texttt">";"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">n</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>の規則は,現在レイアウトの位置と一致した改行を見つけると <tt class="docutils literal">;</tt> を挿入していく.まあこれはいいだろう.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mtext mathvariant="monospace">"}"</mtext><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mo stretchy="false">⟨</mo><mi>n</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>m</mi><mo>:</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>n</mi><mo><</mo><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = \texttt{"\}"}:L_1(t:\mathit{ts}, \mathit{ms}')\hspace{1em} (t = \langle n\rangle, \mathit{ms} = m:\mathit{ms}', n < m)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord texttt">"}"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">n</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9963em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span></span></div>
<p>の規則は,現在レイアウトの位置よりインデントが下がった場合は,そこでレイアウトを閉じる.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mo stretchy="false">⟨</mo><mi>n</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = L_1(\mathit{ts}, \mathit{ms})\hspace{1em} (t = \langle n\rangle, \text{otherwise})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal">n</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span></span></div>
<p>の規則は,現レイアウトの位置よりインデントが上の場合やレイアウトがまだ開始されていない場合,改行位置情報を無視する.これらにより,改行の情報は現在のレイアウトの状態により適切なレイアウトトークンへと置き換えられる.次に</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mtext mathvariant="monospace">"{"</mtext><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>n</mi><mo>:</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mo stretchy="false">{</mo><mi>n</mi><mo stretchy="false">}</mo><mo separator="true">,</mo><mo stretchy="false">(</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>m</mi><mo>:</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∧</mo><mi>n</mi><mo>></mo><mi>m</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>ϵ</mi><mo>∧</mo><mi>n</mi><mo>></mo><mn>0</mn><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = \texttt{"\{"}:L_1(\mathit{ts}, n:\mathit{ms})\hspace{1em} (t = \{ n\}, (\mathit{ms} = m:\mathit{ms}' \land n > m) \lor (\mathit{ms} = \epsilon \land n > 0))
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord texttt">"{"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mclose">))</span></span></span></span></span></div>
<p>の規則は,レイアウト開始位置を見て,現在のレイアウトより字下げが行われている場合は中括弧トークンに変換し,スタックにも新しい位置情報を入れておく.その次の規則</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mtext mathvariant="monospace">"{"</mtext><mo>:</mo><mtext mathvariant="monospace">"}"</mtext><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>n</mi><mo stretchy="false">⟩</mo><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mo stretchy="false">{</mo><mi>n</mi><mo stretchy="false">}</mo><mo separator="true">,</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = \texttt{"\{"}:\texttt{"\}"}:L_1(\langle n\rangle:\mathit{ts}, \mathit{ms})\hspace{1em} (t = \{ n\}, \text{otherwise})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord texttt">"{"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord texttt">"}"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(⟨</span><span class="mord mathnormal">n</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span></span></div>
<p>では字下げが行われていない場合は即レイアウトを閉じる.また,この場合改行情報だけは残しておく.これらの規則により,</p>
<pre class="literal-block">
{1} x = 0 where
{5} x1 = 1
<1> y = 0 where
{1} z = 0 where{0}
</pre>
<p>みたいな場合,</p>
<ol class="arabic simple">
<li>最初の <tt class="docutils literal">{1}</tt> を見る場合,スタックが空なため新たなレイアウトを開始し,スタックに <tt class="docutils literal">1</tt> をプッシュする</li>
<li>次の <tt class="docutils literal">{5}</tt> では,現在のレイアウト位置 <tt class="docutils literal">1</tt> より字下げしているため,また新たなレイアウトを開始し,スタックに <tt class="docutils literal">5</tt> をプッシュする</li>
<li><tt class="docutils literal">5</tt> のレイアウトは次の <tt class="docutils literal"><1></tt> で閉じられる</li>
<li>次の <tt class="docutils literal">{1}</tt> では,現在のレイアウト位置 <tt class="docutils literal">1</tt> と同じレイアウト位置なため,レイアウトを即閉じ改行情報を残す.この改行情報により, <tt class="docutils literal">z</tt> の前に <tt class="docutils literal">;</tt> が挿入される</li>
<li>最後の <tt class="docutils literal">{0}</tt> では,現在のレイアウト位置 <tt class="docutils literal">1</tt> よりレイアウト位置が左にあるため,レイアウトを即閉じ改行情報を残す.この改行情報により,残っているレイアウトも全て閉じられる</li>
</ol>
<p>という風な処理になり,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">{</span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">{</span><span class="n">x1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">1</span>
<span class="p">};</span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">where</span>
<span class="p">{};</span><span class="n">z</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">where</span><span class="p">{}}</span>
</pre></div></td></tr></table></div>
<p>というプログラムが出来上がることになる.残りも見ていくと,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mi>t</mi><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mtext mathvariant="monospace">"}"</mtext><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mn>0</mn><mo>:</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = t:L_1(\mathit{ts}, \mathit{ms}')\hspace{1em} (t = \texttt{"\}"}, \mathit{ms} = 0:\mathit{ms}')
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord text"><span class="mord texttt">"}"</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>は明示的な中括弧閉じの場合,レイアウトが明示的な開始がされたか確認する.明示的な開始でなければ</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="normal">f</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">l</mi></mrow><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mtext mathvariant="monospace">"}"</mtext><mo separator="true">,</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = \mathrm{fail}\hspace{1em} (t = \texttt{"\}"}, \text{otherwise})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">fail</span></span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord texttt">"}"</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span></span></div>
<p>の規則によりパースを失敗させる.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mi>t</mi><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mn>0</mn><mo>:</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mtext mathvariant="monospace">"{"</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = t:L_1(\mathit{ts}, 0:\mathit{ms})\hspace{1em} (t = \texttt{"\{"})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord texttt">"{"</span></span><span class="mclose">)</span></span></span></span></span></div>
<p>の規則では,中括弧により明示的なレイアウトを開始する.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mtext mathvariant="monospace">"}"</mtext><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mtext>otherwise</mtext><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>m</mi><mo>:</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>m</mi><mo>></mo><mn>0</mn><mo separator="true">,</mo><mrow><mi mathvariant="normal">p</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">E</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">r</mi></mrow><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = \texttt{"\}"}:L_1(t:\mathit{ts}, \mathit{ms}')\hspace{1em} (\text{otherwise}, \mathit{ms} = m:\mathit{ms}', m > 0, \mathrm{parseError}(t))
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord texttt">"}"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord">otherwise</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9963em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">parseError</span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">))</span></span></span></span></span></div>
<p>の規則は,冒頭で問題にした規則で,パースエラーが起きる位置で暗黙のレイアウトを自動で閉じるというものだ.他の場合は</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mi>t</mi><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = t:L_1(\mathit{ts}, \mathit{ms})\hspace{1em} (\text{otherwise})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span></span></div>
<p>の規則により単にトークンを受け流していく.最後に入力トークンがなくなった時は,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>ϵ</mi><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>ϵ</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>ϵ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">"{"</mtext><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>ϵ</mi><mo separator="true">,</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>m</mi><mo>:</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>m</mi><mo>></mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">f</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">l</mi></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mn>0</mn><mo>:</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
L_1(\epsilon, \mathit{ms}) = \left\{\begin{array}{ll}
\epsilon &(\mathit{ms} = \epsilon) \\
\texttt{"\{"}:L_1(\epsilon, \mathit{ms}') &(\mathit{ms} = m:\mathit{ms}', m > 0) \\
\mathrm{fail} &(\mathit{ms} = 0:\mathit{ms}')
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-2.5em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.492em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.016em;width:0.8889em;"><svg height="0.016em" preserveaspectratio="xMinYMin" style="width:0.8889em" viewbox="0 0 888.89 16" width="0.8889em" xmlns="http://www.w3.org/2000/svg"><path d="M384 0 H504 V16 H384z M384 0 H504 V16 H384z"></path></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.016em;width:0.8889em;"><svg height="0.016em" preserveaspectratio="xMinYMin" style="width:0.8889em" viewbox="0 0 888.89 16" width="0.8889em" xmlns="http://www.w3.org/2000/svg"><path d="M384 0 H504 V16 H384z M384 0 H504 V16 H384z"></path></svg></span></span><span style="top:-4.3em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord texttt">"{"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">fail</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<p>の規則により,閉じていないレイアウトを閉じていく.その中に明示的な開始によるレイアウトがあった時はパースエラーにする.これが標準仕様の全容になる.</p>
<p>これを文脈付き PEG にどう変換していくかだが,基本的には1段目のレイアウト処理は少し改良しつつそのまま残し,2段目のレイアウト処理を文法に統合するといった感じになる.まず,レイアウト処理を</p>
<img alt="新しいレイアウト処理" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/02/contextual-peg-parser/contextual-peg-parser/new-layout-preprocess.png"/>
<p>のように変更する.主な変更点は,以下の2点:</p>
<ul class="simple">
<li>新規レイアウト開始トークンの後に,改行トークンも続くようにしたこと</li>
<li>入力終了時の位置を <tt class="docutils literal">0</tt> でなく <tt class="docutils literal">1</tt> に変更</li>
</ul>
<p>その変更の意味は置いといて,文法の方も載せておく:</p>
<img alt="レイアウト処理文脈付き文法" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/02/contextual-peg-parser/contextual-peg-parser/new-grammar-with-layout-process.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>e</mi><mi>c</mi><mi>l</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{decls}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">decls</span></span></span></span></span></span> はレイアウトルールを処理する文法の代表として載せている.レイアウトルールを適用する場所では,このように <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>b</mi><mi>o</mi></mrow><annotation encoding="application/x-tex">\mathit{expbo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">expbo</span></span></span></span></span></span>, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>b</mi><mi>c</mi></mrow><annotation encoding="application/x-tex">\mathit{expbc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">expbc</span></span></span></span></span></span>, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>m</mi><mi>p</mi><mi>b</mi><mi>o</mi></mrow><annotation encoding="application/x-tex">\mathit{impbo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">impbo</span></span></span></span></span></span>, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>m</mi><mi>p</mi><mi>b</mi><mi>c</mi></mrow><annotation encoding="application/x-tex">\mathit{impbc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">impbc</span></span></span></span></span></span> で囲むようにする.</p>
<p>さて,肝心の文脈操作の方だが,文脈にはレイアウトスタックをそのまま使う. <tt class="docutils literal">0</tt> が明示的なレイアウト位置,それより上の値は暗黙的なレイアウトの開始位置を表す.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>b</mi><mi>o</mi></mrow><annotation encoding="application/x-tex">\mathit{expbo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">expbo</span></span></span></span></span></span>, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>b</mi><mi>c</mi></mrow><annotation encoding="application/x-tex">\mathit{expbc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">expbc</span></span></span></span></span></span> についてはいいだろう. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>m</mi><mi>p</mi><mi>b</mi><mi>o</mi></mrow><annotation encoding="application/x-tex">\mathit{impbo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">impbo</span></span></span></span></span></span> に2つの規則は元々のレイアウト処理関数の</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mtext mathvariant="monospace">"{"</mtext><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>n</mi><mo>:</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mo stretchy="false">{</mo><mi>n</mi><mo stretchy="false">}</mo><mo separator="true">,</mo><mo stretchy="false">(</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>m</mi><mo>:</mo><msup><mrow><mi>m</mi><mi>s</mi></mrow><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∧</mo><mi>n</mi><mo>></mo><mi>m</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo>=</mo><mi>ϵ</mi><mo>∧</mo><mi>n</mi><mo>></mo><mn>0</mn><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = \texttt{"\{"}:L_1(\mathit{ts}, n:\mathit{ms})\hspace{1em} (t = \{ n\}, (\mathit{ms} = m:\mathit{ms}' \land n > m) \lor (\mathit{ms} = \epsilon \land n > 0))
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord texttt">"{"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ms</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mclose">))</span></span></span></span></span></div>
<p>の規則に対応するものになる.最後の一つは,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mi>t</mi><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo>=</mo><mtext mathvariant="monospace">"{"</mtext><mo>:</mo><mtext mathvariant="monospace">"}"</mtext><mo>:</mo><msub><mi>L</mi><mn>1</mn></msub><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>n</mi><mo stretchy="false">⟩</mo><mo>:</mo><mrow><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>m</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mi>t</mi><mo>=</mo><mo stretchy="false">{</mo><mi>n</mi><mo stretchy="false">}</mo><mo separator="true">,</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
L_1(t:\mathit{ts}, \mathit{ms}) = \texttt{"\{"}:\texttt{"\}"}:L_1(\langle n\rangle:\mathit{ts}, \mathit{ms})\hspace{1em} (t = \{ n\}, \text{otherwise})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord texttt">"{"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord texttt">"}"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(⟨</span><span class="mord mathnormal">n</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ms</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span></span></div>
<p>の規則の一旦を担うものになる.今回の前処理では, <tt class="docutils literal">{n}</tt> の後に <tt class="docutils literal"><n></tt> が挿入されるため,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n + 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> をスタックにプッシュしておくと強制的にレイアウトの字下げ判定が入り,後段の処理で即 <tt class="docutils literal">}</tt> が挿入されることになる.元の処理と比べて面倒になっているように見えるが,むしろ元の処理は実は <tt class="docutils literal">{n}</tt> がレイアウト開始と改行情報の両方の役割を担っていてそれを今回分離したからだ.実際上で挙げた元のレイアウト処理では, <tt class="docutils literal">{n}</tt> を処理した後後段の処理を <tt class="docutils literal"><n></tt> を挿入し直して行っている.このトークンの挿入の代わりに,レイアウトを閉じる処理を全て一箇所にまとめるということを今回は行なっている.これが前処理時,元の処理では挿入していなかった <tt class="docutils literal"><n></tt> をわざわざ <tt class="docutils literal">{n}</tt> の後に挿入するようにした理由になる.</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>m</mi><mi>p</mi><mi>b</mi><mi>c</mi></mrow><annotation encoding="application/x-tex">\mathit{impbc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">impbc</span></span></span></span></span></span> はすごく単純になっている.今回の ptera では Haskell パーサ実装は,PEG で文法を書いているので貪欲にパースが行われる.つまり,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>m</mi><mi>p</mi><mi>b</mi><mi>c</mi></mrow><annotation encoding="application/x-tex">\mathit{impbc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">impbc</span></span></span></span></span></span> にたどり着くということは,それ以上パースできるものがないということに他ならない.つまりはそのままパースを進めるとパースエラーになると言うことだ.これは冒頭に述べたパースエラー時のレイアウト自動終了を体現したものと同時に,字下げ時のレイアウト自動終了も包含している.今回の文法では,レイアウトの改行情報を扱うのは <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>e</mi><mi>m</mi><mi>i</mi></mrow><annotation encoding="application/x-tex">\mathit{semi}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6554em;"></span><span class="mord"><span class="mord mathit">semi</span></span></span></span></span></span> の規則と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">s</mi><mi mathvariant="bold">k</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">p</mi></mrow><annotation encoding="application/x-tex">\mathbf{skip}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">skip</span></span></span></span></span></span> の規則だけだ.そしてこれらの規則では,現在のレイアウトの開始位置以降に改行位置がある場合のみパースが成功する.逆に言えばレイアウト開始位置より手前の場合,パースに失敗する.これにより,字下げ時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>m</mi><mi>p</mi><mi>b</mi><mi>c</mi></mrow><annotation encoding="application/x-tex">\mathit{impbc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">impbc</span></span></span></span></span></span> がリデュースされる感じになる.</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>e</mi><mi>m</mi><mi>i</mi></mrow><annotation encoding="application/x-tex">\mathit{semi}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6554em;"></span><span class="mord"><span class="mord mathit">semi</span></span></span></span></span></span> はまあいいだろう.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">s</mi><mi mathvariant="bold">k</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">p</mi></mrow><annotation encoding="application/x-tex">\mathbf{skip}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">skip</span></span></span></span></span></span> は特殊な非終端記号.この規則は全ての終端記号の手前で評価される.例えば,</p>
<pre class="literal-block">
A ::= "b" A "c"
</pre>
<p>みたいな規則があった時,これは</p>
<pre class="literal-block">
A ::= skip "b" A skip "c"
</pre>
<p>みたいな感じになる.これにより各トークンが消費される際,レイアウトに関与しない改行情報はスキップすることで,レイアウト処理を完結させていく.この特殊な非終端記号については,ptera では特に特別な機能を入れず対応しており,終端記号を作る API をラップし必ず <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">s</mi><mi mathvariant="bold">k</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">p</mi></mrow><annotation encoding="application/x-tex">\mathbf{skip}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">skip</span></span></span></span></span></span> がその手前に来るようにしている.</p>
<p>完全なパーサの規則については,<a class="reference external" href="https://github.com/mizunashi-mana/ptera/blob/ptera-th-0.2.0.0/example/haskell2010/src/Parser/Rules.hs">https://github.com/mizunashi-mana/ptera/blob/ptera-th-0.2.0.0/example/haskell2010/src/Parser/Rules.hs</a> を参照して欲しい.この規則により,GHC よりかなり見通しの良いパーサが実装でき,また例を見てもらうと分かると思うが,PEG で文法を書くことでほぼ Haskell Language Report の規則をそのまま表現できるという感じ <a class="footnote-reference" href="#notice-haskell-peg-grammar" id="auto-id-7">[6]</a>.</p>
</div>
<div class="section" id="srb">
<h2>文脈を考慮した SRB<a class="headerlink" href="#srb" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,ここまでは文脈付き PEG で何を実現したいかの話をしてきたが,では具体的に文脈付き PEG パーサをどう生成するかの話もしておく. <a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2021/11/peg-parser-generating-by-ptera/">前回</a> は,最終的に PEG を SRB という機械に変換し,パーサを生成する方法を紹介した.今回もその方法は基本的に変更はない.ただし,SRB を文脈を考慮して修正したのと,先読みの強化をおこなっている.まずは,SRB の修正部分について話しておこう.といっても,修正自体は文脈が変わったらメモリをまっさらにするだけだが.</p>
<p>まず,文脈操作アクションを文法規則に付与する.具体的には,規則それぞれに対しコンテキストを受け取って以下を返す関数を付与する:</p>
<dl class="docutils">
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">n</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">g</mi></mrow><annotation encoding="application/x-tex">\mathrm{nothing}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm" style="margin-right:0.01389em;">nothing</span></span></span></span></span></span></dt>
<dd>更新なし</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">u</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">d</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">e</mi></mrow><mo stretchy="false">(</mo><mrow><mi>c</mi><mi>t</mi><mi>x</mi></mrow><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{update}(\mathit{ctx})</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">update</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">ctx</span></span><span class="mclose">)</span></span></span></span></span></dt>
<dd>コンテキストを <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>c</mi><mi>t</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\mathit{ctx}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord"><span class="mord mathit">ctx</span></span></span></span></span></span> に更新する</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">f</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">l</mi></mrow><annotation encoding="application/x-tex">\mathrm{fail}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">fail</span></span></span></span></span></span></dt>
<dd>リデュースを失敗させる</dd>
</dl>
<p>コンテキストの集合を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> としてこれらの集合を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">A</mi><mo stretchy="false">(</mo><mi>C</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{A}(C)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal">A</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">)</span></span></span></span></span> と表現する時,アクションは <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi mathvariant="script">A</mi><mo stretchy="false">(</mo><mi>C</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f: C \to \mathcal{A}(C)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal">A</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">)</span></span></span></span></span> のような関数となる.この関数は,例えば</p>
<pre class="literal-block">
{ l ↦ l | front(l) = "a" }
</pre>
<p>のような文脈操作は,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi><mo>↦</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">n</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">g</mi></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>l</mi><mo>=</mo><mtext mathvariant="monospace">"a"</mtext><mo>:</mo><msup><mi>l</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">f</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">l</mi></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
l \mapsto \left\{\begin{array}{ll}
\mathrm{nothing} &(l = \texttt{"a"}:l') \\
\mathrm{fail} &(\text{otherwise})
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7054em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm" style="margin-right:0.01389em;">nothing</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">fail</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord texttt">"a"</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<p>のような関数で表現する.この関数を SRB の操作,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">r</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">d</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">c</mi><mi mathvariant="normal">e</mi></mrow><annotation encoding="application/x-tex">\mathrm{reduce}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">reduce</span></span></span></span></span></span>, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">p</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{pushnot}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">pushnot</span></span></span></span></span></span> にパラメータとして付与する.そして,これを元に SRB の意味論を以下のように修正する:</p>
<img alt="修正された SRB の意味論" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/02/contextual-peg-parser/contextual-peg-parser/srb-semantics.png"/>
<p>異なる部分は,</p>
<ul class="simple">
<li>文脈をそれぞれの状態に付与する</li>
<li>文脈が変わったタイミングでメモは抹消</li>
<li>過去の文脈は覚えておき,バックトラック時に必要に応じて文脈を戻す</li>
</ul>
<p>という感じ.なお,過去の文脈を全て覚えておくのはいささか微妙だが,実際の実装ではバックトラックが発生する場合のみ必要な文脈だけを覚えておくようにしている.こんな感じで,少々手を加えれば SRB の方は対応できる.</p>
</div>
<div class="section" id="auto-id-9">
<h2>先読みの強化<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,今回の実装でもう一つ大きく変更したのが,先読みの強化だ.ptera の実装は先読みによりバックトラックをなるべく少なくすることで,実用的なパースを行おうというものだ.ただ,今までの実装は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">\epsilon</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span></span></span></span></span> 規則をどこかに含んでいるとそこで先読みを諦めてしまう.例えば,</p>
<pre class="literal-block">
abc :: ab "c"
ab ::= "a" | "b" |
</pre>
<p>みたいな規則があった時,通常 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">c</mi></mrow><annotation encoding="application/x-tex">\mathrm{abc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">abc</span></span></span></span></span></span> の1文字先読み結果は a / b / c になるが,これまでの ptera は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">c</mi></mrow><annotation encoding="application/x-tex">\mathrm{abc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">abc</span></span></span></span></span></span> の先読みに <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi></mrow><annotation encoding="application/x-tex">\mathrm{ab}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">ab</span></span></span></span></span></span> の結果をそのまま使っていた.そして,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">\epsilon</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span></span></span></span></span> の先読みは何が次に来ても良いと言うものだったので,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi></mrow><annotation encoding="application/x-tex">\mathrm{ab}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">ab</span></span></span></span></span></span> の結果も全てを許容するというものになり,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">c</mi></mrow><annotation encoding="application/x-tex">\mathrm{abc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">abc</span></span></span></span></span></span> もそれを継承することになる.その結果先読みが機能せず,無駄なバックトラックが発生しやすくなってしまう.特に今回の Haskell パーサの実装では,終端記号の前に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">\epsilon</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span></span></span></span></span> 規則を含む <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">s</mi><mi mathvariant="bold">k</mi><mi mathvariant="bold">i</mi><mi mathvariant="bold">p</mi></mrow><annotation encoding="application/x-tex">\mathbf{skip}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">skip</span></span></span></span></span></span> 記号が置かれるため,ほとんど先読みが機能しなくなってしまっていた.そこで,もう少し先読みを強化してみるかと言う感じになった.</p>
<p>今までの先読みは先に続く文字で許容するものを特定すると言うものだったが,先読み強化にあたって何もトークンを消費しないで先に行ける空遷移 (イプシロン遷移)とトークンを消費する場合の先読み情報を明確に区別するようにした.これにより,上の例で今まで <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi></mrow><annotation encoding="application/x-tex">\mathrm{ab}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">ab</span></span></span></span></span></span> の先読み情報は「次に何があっても良い」と言うものだったのが,「a / b を消費して進むかまたは空遷移」というものに変わる.これにより,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">c</mi></mrow><annotation encoding="application/x-tex">\mathrm{abc}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">abc</span></span></span></span></span></span> の先読みの際 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">b</mi></mrow><annotation encoding="application/x-tex">\mathrm{ab}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">ab</span></span></span></span></span></span> の先読み情報見つつ,空遷移の場合はさらに先を見てみて c を必ず消費するので,先読み結果は「a / b / c いずれかを消費し進む」と結論づけることができるみたいな感じ.</p>
<p>ただ,この修正で変更すべき範囲は結構広い.今までは規則のそれぞれの位置で非終端記号があるならその非終端記号の先読み情報をそのまま使う,終端記号であればそれをそのまま先読み情報とするみたいな感じで先読みを行なっていた.ところが,今回の変更を適用するためには非終端記号の場合先読み情報をそのまま使えるわけではなく,空遷移が入っている場合はさらに先を読む必要が出てくる.そこら辺を踏まえ大きくアルゴリズムを修正することになった.修正した先読みのアルゴリズムは以下のようになる:</p>
<img alt="PEG の先読み生成アルゴリズム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2022/02/contextual-peg-parser/contextual-peg-parser/lookahead-pseudocode.png"/>
<p>このアルゴリズムは最終的に,PEG の各規則ごとにその先読み結果をつけた先読みテーブルを返す.先読みはそれぞれ,消費が発生する場合の消費する可能性のあるトークンの集合と,空遷移が発生するかの真偽値の組から成っている.今回の先読みアルゴリズムは二段構成になっており,まず非終端記号それぞれに対する先読みを行なった後,その結果を元に各規則の正確な先読みを行うようになっている.これはそうしないで正確な先読み一回で済まそうとすると,先読みが循環して正確に行えない場合があるからだ.先読み自体は,空遷移があるなら後ろの先読み結果も使う,空遷移がないなら先読みはそこで完結みたいな感じのことを書き下すとこうなると言う感じ.後は否定の場合を少しだけ正確にしている(といっても焼け石に水という感じだが).とりあえず,これにより否定が入らないなら本当の1文字先読みが実現できるはず.</p>
</div>
<div class="section" id="auto-id-10">
<h2>まとめ<a class="headerlink" href="#auto-id-10" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Haskell パーサが割とちゃんと狙い通りに実現できたので満足している.また先読み強化により,Haskell パーサのバックトラックも劇的に改善した.もう少し考えるべき点はまあまだもう少しあるんだが,とりあえず今回はこれで満足.後はまた使いながら改善していこうかなと.</p>
<p>当初は PEG 使えば割と楽できるんじゃね?と雑に考えていたが,PEG は PEG なりに苦労する部分があると気づけたのは大きいと思う.また,PEG そのものではないが,PEG に文脈をつけてもそれなりに何とかなり,レイアウトルールを割と綺麗に扱えるっぽいと分かったのも良かった.とりあえず,これで ptera 弄るのは一段楽かなという感じ.今回はこれで.</p>
<table class="docutils footnote" frame="void" id="qualified-tokens" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td>モジュール修飾子周りの仕様は,実装者に優しいかと言われるとちょっと微妙な気もするが.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="haskell-layout-rule" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label">[2]</td><td><em>(<a class="fn-backref" href="#auto-id-2">1</a>, <a class="fn-backref" href="#auto-id-6">2</a>)</em> <a class="reference external" href="https://www.haskell.org/onlinereport/haskell2010/haskellch10.html#x17-17800010.3">https://www.haskell.org/onlinereport/haskell2010/haskellch10.html#x17-17800010.3</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="ghc-layout-maintenance-cost" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[3]</a></td><td>Haskell 98 から Haskell 2010 でレイアウトルールの仕様が一部変わったりなどや,構文を拡張する GHC 拡張などの影響も大きいが.最近でまだ閉じれられていないレイアウトルール関連の問題としては,<a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/-/issues/17359">https://gitlab.haskell.org/ghc/ghc/-/issues/17359</a> があるようだ.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="hse-empty-where-issue" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[4]</a></td><td><a class="reference external" href="https://github.com/haskell-suite/haskell-src-exts/issues/282">https://github.com/haskell-suite/haskell-src-exts/issues/282</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="other-implemententation-layout-rule" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[5]</a></td><td>HSE もそれに倣ってか,同じようにトークナイザとパーサが連動している.PureScript などの Haskell 系列のものも大体似たようなことをやっているあたり,かなり根深い問題であると言うことだろう.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-haskell-peg-grammar" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[6]</a></td><td>最も左再帰や曖昧性がある箇所については修正が必要で,その部分は少しずれているが.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2022/02/contextual-peg-parser.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2022/02/contextual-peg-parser.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>upLaTeX から LuaTeX に移行する2021-12-26T04:26:47+09:002021-12-26T04:26:47+09:00Mizunashi Manatag:mizunashi-mana.github.io,2021-12-26:/blog/posts/2021/12/migrate-to-luatexja/<p>今まで日本語文書作成で upLaTeX を使っていたのだが,体験が微妙だったので最近 LuaTeX に移行した.特に数式フォントとして …</p><p>今まで日本語文書作成で upLaTeX を使っていたのだが,体験が微妙だったので最近 LuaTeX に移行した.特に数式フォントとして,STIX2 を使っていたのだが,文字が崩れたりするのをなんとかしたくて,<tt class="docutils literal"><span class="pre">unicode-math</span></tt> を採用するために移行したというのが大きい.そこまで大変でもなかったのだが,詰まるポイントはいくつかあったのでその備忘録.</p>
<p>移行したのは <a class="reference external" href="https://github.com/mizunashi-mana/proglang-notes">https://github.com/mizunashi-mana/proglang-notes</a> なので,最終形見たかったらこちらをどうぞ.</p>
<div class="section" id="auto-id-1">
<h2>構成の変更<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今までは,upLaTeX と <tt class="docutils literal">dvipdfmx</tt> を使っていて, <tt class="docutils literal">jsbook</tt> をクラスに使った構成にしていた.</p>
<ul class="simple">
<li>ビルドは, <tt class="docutils literal">latexmk</tt> 経由で <tt class="docutils literal">uplatex</tt> と <tt class="docutils literal">dvipdfmx</tt> から PDF 生成</li>
<li>フォントは,デフォルト Latin Modern で,日本語は IPAex の埋め込み,数式は STIX2 Type1</li>
</ul>
<p>みたいな感じだ.まあ良くある構成.これを, <tt class="docutils literal">ltjsbook</tt> クラスを使い</p>
<ul class="simple">
<li>ビルドは, <tt class="docutils literal">latexmk</tt> 経由で <tt class="docutils literal">luatex</tt> から PDF 生成</li>
<li>フォントは,デフォルトと数式は STIX2 OpenType,日本語は原ノ味</li>
</ul>
<p>という構成にした.また,今までは <tt class="docutils literal"><span class="pre">stix2-type1</span></tt> パッケージを直接使って Unicode 文字経由の数式記号マクロを使っていたが,これを <tt class="docutils literal"><span class="pre">unicode-math</span></tt> 経由で使うようにした.</p>
</div>
<div class="section" id="latexmk">
<h2>Latexmk の設定<a class="headerlink" href="#latexmk" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まず <tt class="docutils literal">latexmk</tt> の設定を変更する.今まで <tt class="docutils literal">uplatex</tt> / <tt class="docutils literal">dvipdfmx</tt> を使っていたのを, <tt class="docutils literal">luatex</tt> を使うよう変更した.設定ファイルは以下:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span></pre></div></td><td class="code"><div><pre><span></span><span class="ch">#!/usr/bin/env perl</span>
<span class="k">use</span><span class="w"> </span><span class="nn">v5</span><span class="mf">.10</span><span class="p">;</span>
<span class="k">use</span><span class="w"> </span><span class="nn">experimental</span><span class="w"> </span><span class="sx">qw(smartmatch)</span><span class="p">;</span>
<span class="c1"># tex options</span>
<span class="nv">$lualatex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'lualatex -shell-escape -synctex=1 -interaction=nonstopmode'</span><span class="p">;</span>
<span class="nv">$pdflualatex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$lualatex</span><span class="p">;</span>
<span class="nv">$biber</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'biber %O --bblencoding=utf8 -u -U --output_safechars %B'</span><span class="p">;</span>
<span class="nv">$bibtex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'bibtex %O %B'</span><span class="p">;</span>
<span class="nv">$makeindex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'mendex %O -o %D %S'</span><span class="p">;</span>
<span class="nv">$max_repeat</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span>
<span class="nv">$pdf_mode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">4</span><span class="p">;</span>
<span class="nv">$pvc_view_file_via_temporary</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="c1"># default preview</span>
<span class="n">given</span><span class="w"> </span><span class="p">(</span><span class="vg">$^O</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="p">(</span><span class="sr">/MSWin32/</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nv">$pdf_previewer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'start'</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="p">(</span><span class="sr">/darwin/</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nv">$pdf_previewer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'open'</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">default</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nv">$pdf_previewer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'evince'</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="c1"># local config</span>
<span class="nv">$local_latexmkrc_path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">'./.latexmkrc.local'</span><span class="p">;</span>
<span class="k">require</span><span class="w"> </span><span class="nv">$local_latexmkrc_path</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">-</span><span class="n">e</span><span class="w"> </span><span class="nv">$local_latexmkrc_path</span><span class="p">;</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">$pdf_mode = 4;</tt> がポイント. <tt class="docutils literal">latexmk</tt> の <tt class="docutils literal">$pdf_mode</tt> は,デフォルトの PDF 生成モードを指定できる.指定できるのは以下のモード <a class="footnote-reference" href="#latexmk-manual" id="auto-id-2">[1]</a>:</p>
<ul class="simple">
<li>0 の場合, <tt class="docutils literal">$latex</tt> コマンドを実行するだけ.PDF は生成しない</li>
<li>1 の場合, <tt class="docutils literal">$pdflatex</tt> コマンドによって PDF を生成する</li>
<li>2 の場合, <tt class="docutils literal">$latex</tt> コマンドを実行した後, <tt class="docutils literal">$dvips</tt> コマンドで一旦 PS ファイルを生成し, <tt class="docutils literal">ps2pdf</tt> コマンドで PS ファイルを PDF ファイルに変換する</li>
<li>3 の場合, <tt class="docutils literal">$latex</tt> コマンドを実行した後, <tt class="docutils literal">$dvipdf</tt> コマンドで PDF ファイルに変換する</li>
<li>4 の場合, <tt class="docutils literal">$lualatex</tt> コマンドによって PDF を生成する</li>
<li>5 の場合, <tt class="docutils literal">$xelatex</tt> コマンドを実行した後, <tt class="docutils literal">$xdvipdfmx</tt> コマンドで PDF ファイルに変換する</li>
</ul>
<p>今までは 3 を指定していたが,今回から 4 を指定している.LuaTeX は基本 pdflatex の後継で,DVI ファイルを経由せず直接 PDF を生成する.この設定により, <tt class="docutils literal">latexmk main.tex</tt> を実行すると <tt class="docutils literal">main.tex</tt> から <tt class="docutils literal">lualatex</tt> コマンドで PDF を生成する.設定はよくあるやつだが, <tt class="docutils literal"><span class="pre">-shell-escape</span></tt> オプションだけは特別に <tt class="docutils literal">minted</tt> パッケージのために付けている. <tt class="docutils literal">minted</tt> 使わないなら付けないほうがいいと思う.</p>
</div>
<div class="section" id="auto-id-3">
<h2>必要なパッケージ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>LuaTeX で日本語を書くには,以下のパッケージをインストールする:</p>
<ul class="simple">
<li><tt class="docutils literal">luatex</tt></li>
<li><tt class="docutils literal">luatexja</tt></li>
</ul>
<p>これらは <tt class="docutils literal"><span class="pre">collection-luatex</span></tt>, <tt class="docutils literal"><span class="pre">collection-langjapanese</span></tt> に含まれている.後今回は</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">unicode-math</span></tt></li>
<li><tt class="docutils literal"><span class="pre">stix2-otf</span></tt></li>
</ul>
<p>を数式用に使う.後は適当に使うやつをインストールする.</p>
</div>
<div class="section" id="auto-id-4">
<h2>プリアンブル<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>LuaTeX-ja では,jsclasses 互換のクラスがいくつか提供されており,和文文書を書く時は以下のものが使える <a class="footnote-reference" href="#ltjsclasses-manual" id="auto-id-5">[2]</a>.</p>
<dl class="docutils">
<dt><tt class="docutils literal">ltjsarticle</tt></dt>
<dd>論文・レポート用</dd>
<dt><tt class="docutils literal">ltjsbook</tt></dt>
<dd>書籍用</dd>
<dt><tt class="docutils literal">ltjsreport</tt></dt>
<dd>レポート用</dd>
</dl>
<p>元々 <tt class="docutils literal">jsbook</tt> を使っていたので,今回は <tt class="docutils literal">ltjsbook</tt> を使う:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">\documentclass</span>[
luatex,
japanese,
unicode,
titlepage,
pdfusetitle
]<span class="nb">{</span>ltjsbook<span class="nb">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">luatex</tt> オプションはドライバ判定のため, <tt class="docutils literal">japanese</tt> は元々 <tt class="docutils literal">babel</tt> のためにつけていたものの流用, <tt class="docutils literal">titlepage</tt> はお好みで,他は <tt class="docutils literal">hyperref</tt> のためのオプションという感じになる.後は適当に使うパッケージを読み込んでおく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">\usepackage</span><span class="nb">{</span>luatexja<span class="nb">}</span>
<span class="k">\usepackage</span><span class="nb">{</span>hyperref<span class="nb">}</span>
<span class="k">\usepackage</span><span class="nb">{</span>babel<span class="nb">}</span>
<span class="k">\usepackage</span><span class="nb">{</span>bookmark<span class="nb">}</span>
<span class="k">\usepackage</span><span class="na">[no-math,haranoaji,deluxe]</span><span class="nb">{</span>luatexja-preset<span class="nb">}</span>
<span class="k">\usepackage</span><span class="nb">{</span>unicode-math<span class="nb">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal"><span class="pre">luatexja-preset</span></tt> は font preset を指定するとフォントをいい感じに諸々設定してくれるやつらしい.今回は haranoaji フォントを使うよう指定している. <tt class="docutils literal">deluxe</tt> オプションを指定することで,使えるウェイトを増やせる.後は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">\setmainfont</span><span class="nb">{</span>STIX Two Text<span class="nb">}</span>
<span class="k">\setmathfont</span><span class="nb">{</span>STIX Two Math<span class="nb">}</span>
<span class="c">% some math fonts not support bold</span>
<span class="k">\DeclareFontShape</span><span class="nb">{</span>TU<span class="nb">}{</span>STIXTwoMath(1)<span class="nb">}{</span>b<span class="nb">}{</span>n<span class="nb">}{</span><->ssub*STIXTwoMath(1)/m/n<span class="nb">}{}</span>
<span class="k">\DeclareFontShape</span><span class="nb">{</span>TU<span class="nb">}{</span>STIXTwoMath(2)<span class="nb">}{</span>b<span class="nb">}{</span>n<span class="nb">}{</span><->ssub*STIXTwoMath(2)/m/n<span class="nb">}{}</span>
<span class="k">\DeclareFontShape</span><span class="nb">{</span>TU<span class="nb">}{</span>STIXTwoMath(3)<span class="nb">}{</span>b<span class="nb">}{</span>n<span class="nb">}{</span><->ssub*STIXTwoMath(3)/m/n<span class="nb">}{}</span>
</pre></div></td></tr></table></div>
<p>欧文のテキストフォント,数式フォントに STIX2 を指定する.よく分からないが,フォントシェイプの警告がいくつか出ていたので,フォールバックを明示的に指定している.ここら辺はちゃんと調べたほうが良さそうだが,とりあえずこれでいいかなという.以下が表示サンプル:</p>
<dl class="docutils">
<dt>アルファベット</dt>
<dd><img alt="アルファベットのサンプル" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2021/12/migrate-to-luatexja/migrate-to-luatexja/alphabet-sample.png"/>
</dd>
<dt>いろは</dt>
<dd><img alt="いろはのサンプル" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2021/12/migrate-to-luatexja/migrate-to-luatexja/iroha-sample.png"/>
</dd>
<dt>数式</dt>
<dd><img alt="数式のサンプル" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2021/12/migrate-to-luatexja/migrate-to-luatexja/math-alphabet-sample.png"/>
</dd>
</dl>
</div>
<div class="section" id="auto-id-6">
<h2>その他<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今まで XY-pic を使っていたが,LuaTeX では使えないらしいので,これからは tikz 直接使っていく感じにする.後,数式の記号は今まで <tt class="docutils literal">amssymb</tt>, <tt class="docutils literal">mathtools</tt>, <tt class="docutils literal"><span class="pre">stix2-type1</span></tt> を併用していたが, <tt class="docutils literal"><span class="pre">unicode-math</span></tt> に一元化した.多少今まで使っていた記号マクロから名前が変わっていた部分はあるが,基本特に使える文字に変化はなかった. <tt class="docutils literal"><span class="pre">unicode-math</span></tt> に一元化したことによって,記号の名前か Unicode コードポイントが分かれば <tt class="docutils literal"><span class="pre">unicode-math</span></tt> マニュアルの <a class="reference external" href="https://mirrors.concertpass.com/tex-archive/macros/unicodetex/latex/unicode-math/unimath-symbols.pdf">記号一覧</a> から検索できる.Detexify が対応していないので,名前が何も分からないと不便な場合もあるが,まあ大体は今までより利便性が上がっているはず.</p>
<p>他に, <tt class="docutils literal">amsalpha</tt> を <tt class="docutils literal">bibliographystyle</tt> に使っていたが,これが使えなかった.こっちも原因はあまり調べていないが,とりあえず,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">\bibliographystyle</span><span class="nb">{</span>alpha<span class="nb">}</span>
</pre></div></td></tr></table></div>
<p>に切り替えて対応している.</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>LuaTeX に移行する際の諸々を書いた.<tt class="docutils literal">\xymatrix</tt> が使えなくなったのはちょっと残念だが,他はそれほど困っていない.まだ使って日が浅いが,なんとかなるかなあという感じ.今回はそんだけで.では.</p>
<table class="docutils footnote" frame="void" id="latexmk-manual" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><a class="reference external" href="https://mirrors.rit.edu/CTAN/support/latexmk/latexmk.pdf">https://mirrors.rit.edu/CTAN/support/latexmk/latexmk.pdf</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="ltjsclasses-manual" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[2]</a></td><td><a class="reference external" href="https://mirrors.ibiblio.org/CTAN/macros/luatex/generic/luatexja/doc/ltjsclasses.pdf">https://mirrors.ibiblio.org/CTAN/macros/luatex/generic/luatexja/doc/ltjsclasses.pdf</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2021/12/migrate-to-luatexja.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2021/12/migrate-to-luatexja.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>ptera 式 PEG パーサ生成法2021-11-20T21:02:13+09:002021-11-20T21:02:13+09:00Mizunashi Manatag:mizunashi-mana.github.io,2021-11-20:/blog/posts/2021/11/peg-parser-generating-by-ptera/<p>最近 PEG パーサジェネレータライブラリを作っているんだが,一旦区切りがついたので忘れないうちに備忘録をまと …</p><p>最近 PEG パーサジェネレータライブラリを作っているんだが,一旦区切りがついたので忘れないうちに備忘録をまとめておく.</p>
<p>さて,PEG は曖昧さが存在しない言語を定義する為の文法だ.基本的には文法自体は結構単純で書きやすい.構文解析も単純ではある.ただ,愚直に構文解析すると入力の長さに対して指数時間かかってしまうため,取り扱いが少し難しい.ただ,入力の長さ分のメモリを用意することで,解析時間を入力の長さに対して線形時間にする packrat parsing という手法が提案され,最近では PEG をプログラミング言語の文法の定義方法として採用する言語も増えているようだ.</p>
<p>PEG の魅力はなんといっても曖昧さを排除できる点と,文法程度を簡潔にできる点だろう.ただ,あまりいい感じのパーサ生成ライブラリがない場合も多い.Haskell にもあんまりいい感じのがなかった.なので今回は,PEG の勉強がてらパーサ生成ライブラリを作ってみたので,その仕組みについて紹介する.なお,かなり PEG 勉強したてで,既存手法検索してもあんまりいい文献当たらないなあと言う感じで独自の手法に手を染めた話なので,もし他にこれよりいい確立された方法あるよとかあったらぜひ教えてもらえるとって感じだ.</p>
<p>なお,ライブラリ自体は <a class="reference external" href="https://github.com/mizunashi-mana/ptera">https://github.com/mizunashi-mana/ptera</a> で開発中という感じ.</p>
<div class="section" id="peg-parsing-expression-grammar">
<h2>PEG (Parsing Expression Grammar)<a class="headerlink" href="#peg-parsing-expression-grammar" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>PEG は,非終端記号 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span></span></span></span></span>,終端記号 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Σ</mi></mrow><annotation encoding="application/x-tex">\Sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Σ</span></span></span></span></span>,パース規則 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>=</mo><mi>N</mi><mo>→</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">R = N \to E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span>,初期式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mi>S</mi></msub><mo>∈</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">e_S \in E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> で構成される.式は,以下の要素からなる.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right left right" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>e</mi><mo>∈</mo><mi>E</mi><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>σ</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>σ</mi><mo>∈</mo><mi mathvariant="normal">Σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>A</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>A</mi><mo>∈</mo><mi>N</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>ϵ</mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>e</mi><mn>1</mn></msub><mtext> </mtext><msub><mi>e</mi><mn>2</mn></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>e</mi><mn>1</mn></msub><mi mathvariant="normal">/</mi><msub><mi>e</mi><mn>2</mn></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><msup><mi>e</mi><mo>∗</mo></msup></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>e</mi><mo>+</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>e</mi><mo stretchy="false">?</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">&</mi><mi>e</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">!</mo><mi>e</mi></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rlr}
e \in E \mathrel{::=} & \sigma &(\sigma \in \Sigma) \\
\mid & A &(A \in N) \\
\mid & \epsilon \\
\mid & e_1\; e_2 \\
\mid & e_1 / e_2 \\
\mid & e^* \\
\mid & e+ \\
\mid & e? \\
\mid & \& e \\
\mid & !e
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:12em;vertical-align:-5.75em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:6.25em;"><span style="top:-8.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-7.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:1.19em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:2.39em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:5.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:6.25em;"><span style="top:-8.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span><span style="top:-7.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">A</span></span></span><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="mord">+</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="mclose">?</span></span></span><span style="top:1.19em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">&</span><span class="mord mathnormal">e</span></span></span><span style="top:2.39em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mclose">!</span><span class="mord mathnormal">e</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:5.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:6.25em;"><span style="top:-8.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">Σ</span><span class="mclose">)</span></span></span><span style="top:-7.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>この式は次のような意味論を持つ:</p>
<img alt="PEG の意味論" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2021/11/peg-parser-generating-by-ptera/peg-parser-generating-by-ptera/peg-semantics.png"/>
<p>受理条件は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mo stretchy="false">(</mo><mi>N</mi><mo separator="true">,</mo><mi mathvariant="normal">Σ</mi><mo separator="true">,</mo><mi>R</mi><mo separator="true">,</mo><msub><mi>e</mi><mi>S</mi></msub><mo stretchy="false">)</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>=</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>e</mi><mi>S</mi></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>=</mo><mo stretchy="false">{</mo><mi>x</mi><mo>∈</mo><msup><mi mathvariant="normal">Σ</mi><mo>∗</mo></msup><mo>∣</mo><mo stretchy="false">⟨</mo><msub><mi>e</mi><mi>S</mi></msub><mo separator="true">,</mo><mi>x</mi><mo stretchy="false">⟩</mo><mo>→</mo><mi mathvariant="bold">s</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\llbracket (N, \Sigma, R, e_S)\rrbracket = \llbracket e_S\rrbracket = \{x \in\Sigma^* \mid \langle e_S, x\rangle \to \mathbf{s}(x)\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Σ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathbf">s</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)}</span></span></span></span></span> になる.特徴的なのは,分岐 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub><mi mathvariant="normal">/</mi><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_1 / e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> だろう.文脈自由言語の分岐は優先度は特にないが,PEG では1つ目が2つ目より必ず優先される意味論を持つ.後は,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">&</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">\& e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">&</span><span class="mord mathnormal">e</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">!</mo><mi>e</mi></mrow><annotation encoding="application/x-tex">! e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mclose">!</span><span class="mord mathnormal">e</span></span></span></span></span> といった先読み述語を原始構文として持つのも特徴の1つだろうか.ただ,基本的に上の規則をそのまま実装すれば,愚直な構文解析はできる.</p>
<p>さて,愚直な構文解析する場合,基本的に分岐を上から成功するまで順に解析してみてはバックトラックを繰り返すことになる.それぞれの分岐でさらに分岐することもあるわけで,例えば</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right right left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>S</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">→</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">a</mi><mi>A</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">a</mi><mi>S</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mi mathvariant="normal">a</mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>A</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">→</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">a</mi><mi>A</mi></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rrl}
S &\to &\mathrm{a} A \\
&\mid &\mathrm{a} S \\
&\mid &\mathrm{a} \\
A &\to &\mathrm{a} A
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:4.8em;vertical-align:-2.15em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">→</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">→</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathrm">a</span><span class="mord mathnormal">A</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathrm">a</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathrm">a</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathrm">a</span><span class="mord mathnormal">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">a</mi></mrow><annotation encoding="application/x-tex">\mathrm{a}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathrm">a</span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> 個続く文字列を受理させるには,基本的には <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> 回入力文字列を走査することになる.</p>
<p>まあ流石に入力文字列の長さに対して指数時間というのはちょっと微妙なので,線形時間にする Packrat Parsing という手法が提案されている.これもそれほど難しい手法ではない.さて,先ほどの PEG の例で問題だったのは分岐の中でどんどん分岐がネストしていくということだったが,文字列走査が増えることの本質は,同じ文字列走査を何度もやっていることによる.非終端記号 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> は一回走査すればどの地点から解析しようとしても失敗すると分かる.ところが愚直にやる場合,何度も同じ解析をすることになる.Packrat Parsing というのは,この同じ解析を何度もやるのを,一度目の解析結果をメモして二度目以降はそれを流用することで抑えようという手法だ.</p>
<p>Packrat Parsing では,入力文字列の全ての地点と非終端記号に対してメモ化領域を用意する.そして,非終端記号の解析に入る時,結果がメモされていればその結果を流用し,メモされてなければ解析してその結果をメモしておく.これにより,非終端記号の解析は最大でも入力文字列の長さと非終端記号の数の積だけとなる.この手法を用いれば,変数は入力文字列の長さ分だけで,他は文法を固定すると定数分で換算できるので,入力文字列の長さの定数倍分のメモリ領域は必要になるが,線形時間で解析が可能ということになる.</p>
</div>
<div class="section" id="peg-vs-lalr">
<h2>PEG vs LALR<a class="headerlink" href="#peg-vs-lalr" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>とはいえ,まあメモリも線形分消費するわけで,そこら辺は好みが分かれるところだろう.特に,プログラミング言語の構文解析では LALR パーサが主流になっていて,そちらでは Packrat Parsing のようなバックトラックありの線形時間解析ではなく,バックトラックなしに本当に文字列を最初から一度だけ走査していくため,PEG パーサよりパフォーマンス面では優秀ということになるだろう.</p>
<p>エラー箇所の特定もある程度工夫しないと難しい.LALR パーサでは,失敗はそもそも一度しか起こらない為,失敗した地点での規則の候補からエラーの原因を特定しやすい.しかし,PEG の場合バックトラックしながらパースが進んでいく為複数地点で失敗が発生する.しかし,それらが全てエラーの本質とは限らない.例えば,多くのプログラムは複数の文から構成されているが,それぞれの文のパースは多くの場合独立している.そして,それを PEG で解析する場合,一つ一つの文の解析でバックトラックが発生するかもしれない.しかし,文自体のパースに成功したならバックトラック自体は本質的に起こるものであり,プログラムの構文エラーではないのだ.このように,PEG ではエラーの原因を特定しようとすると,失敗した地点の中で構文エラーと捉えるべき失敗を精査する仕組みが必要になる.</p>
<p>このように,実装面で見ると PEG はかなり扱いづらい文法でもある.しかし,PEG にはこのような事情を鑑みても LALR パーサに勝る大きな利点がある.それはパーサの動作が単純であると言う点だ.LALR パーサは,文法からどのようなパーサが生成されるかがかなり捉えづらい.そのため,エラーを起こす規則が分かったとしても,具体的に元の文法でどこの定義の仕方が悪いのかを調べるのは結構難しい.また,元の文法の問題の箇所が分かったとしても,それを自分の要望を満たすように改善する方法を見つけるのにまた手間がかかる.また,本質的に LALR パーサを使っている限りは改善できないといった場合もある.Haskell の do 構文を例に出してみよう.Haskell の do 構文は文脈自由言語で以下のように定義される構文だ:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>l</mi><mi>e</mi><mi>x</mi><mi>p</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">do</mtext><mtext> </mtext><mtext mathvariant="monospace">{</mtext></mrow><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi><mi>s</mi></mrow><mtext mathvariant="monospace">}</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi><mi>s</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi></mrow><mn>1</mn></msub><mo>⋯</mo><msub><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi></mrow><mi>n</mi></msub><mrow><mi>e</mi><mi>x</mi><mi>p</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>e</mi><mi>x</mi><mi>p</mi></mrow><mtext mathvariant="monospace">;</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>p</mi><mi>a</mi><mi>t</mi></mrow><mo><mtext mathvariant="monospace"><-</mtext></mo><mrow><mi>e</mi><mi>x</mi><mi>p</mi></mrow><mtext mathvariant="monospace">;</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">let</mtext><mrow><mi>d</mi><mi>e</mi><mi>c</mi><mi>l</mi><mi>s</mi></mrow><mtext mathvariant="monospace">;</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mtext mathvariant="monospace">;</mtext></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rl}
\mathit{lexp} \mathrel{::=} & \text{\texttt{do \{}} \mathit{stmts} \text{\texttt{\}}} \\
\mathit{stmts} \mathrel{::=} & \mathit{stmt}_1 \cdots \mathit{stmt}_n \mathit{exp} \\
\mathit{stmt} \mathrel{::=} & \mathit{exp} \text{\texttt{;}} \\
\mid & \mathit{pat} \mathrel{\text{\texttt{<-}}} \mathit{exp} \text{\texttt{;}} \\
\mid & \text{\texttt{let}} \mathit{decls} \text{\texttt{;}} \\
\mid & \text{\texttt{;}}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:7.2em;vertical-align:-3.35em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">lexp</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">stmts</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">stmt</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord text"><span class="mord texttt">do {</span></span></span><span class="mord"><span class="mord mathit">stmts</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">}</span></span></span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">stmt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">stmt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathit">exp</span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">exp</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">pat</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord text"><span class="mord texttt"><-</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">exp</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord text"><span class="mord texttt">let</span></span></span><span class="mord"><span class="mord mathit">decls</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi></mrow><annotation encoding="application/x-tex">\mathit{exp}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">exp</span></span></span></span></span></span> ,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mi>a</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">\mathit{pat}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">pat</span></span></span></span></span></span> ,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>e</mi><mi>c</mi><mi>l</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{decls}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">decls</span></span></span></span></span></span> は定義は省略するが,それぞれ式,パターン,定義文の列を表す非終端記号だ.さて,この文のパーサを生成することを考える.しかし,この文をそのままちゃんと扱える LALR パーサジェネレータはおそらくないだろう.問題となるのは <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">\mathit{stmt}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord"><span class="mord mathit">stmt</span></span></span></span></span></span> の最初の2つの選択肢だ.これらをそのまま LALR パーサで扱うとなると,例えば <tt class="docutils literal">x</tt> のようなプログラム片において,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi></mrow><annotation encoding="application/x-tex">\mathit{exp}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">exp</span></span></span></span></span></span> として reduce するか,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mi>a</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">\mathit{pat}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">pat</span></span></span></span></span></span> として reduce するかを決定する機構が必要になる.しかし,この文法を定義したものの意図は,後にくるであろう <tt class="docutils literal"><-</tt> がある場合は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>p</mi><mi>a</mi><mi>t</mi></mrow><mo><mtext mathvariant="monospace"><-</mtext></mo><mrow><mi>e</mi><mi>x</mi><mi>p</mi></mrow><mtext mathvariant="monospace">;</mtext></mrow><annotation encoding="application/x-tex">\mathit{pat} \mathrel{\text{\texttt{<-}}} \mathit{exp} \text{\texttt{;}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">pat</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord text"><span class="mord texttt"><-</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">exp</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span></span></span> の文として,それ以外の時はもう一方の文としてパースしてほしいと言うことだろう.このように先をかなり見ないと前の決定ができないような文法は基本的に LALR では扱えない.もちろん,PEG ではそのまま素直に扱えることになる.</p>
<p>ところで,我らが GHC は LALR パーサジェネレータの Happy を使っているわけだが,そこから分かる通りこの問題は LALR で解決は可能だ.といっても,かなり力技になるが.GHC はここら辺の解決をどうしているかと言うと,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi></mrow><annotation encoding="application/x-tex">\mathit{exp}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">exp</span></span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mi>a</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">\mathit{pat}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">pat</span></span></span></span></span></span> を一つの非終端記号にまとめ,パース結果からどう解釈するか決めてパース結果に対してバリデーションをかますと言う方法をとっている.具体的には,上の規則を以下のような規則に変更する:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>l</mi><mi>e</mi><mi>x</mi><mi>p</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">do</mtext><mtext> </mtext><mtext mathvariant="monospace">{</mtext></mrow><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi><mi>s</mi></mrow><mtext mathvariant="monospace">}</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi><mi>s</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi></mrow><mn>1</mn></msub><mo>⋯</mo><msub><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi></mrow><mi>n</mi></msub><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>p</mi><mi>a</mi><mi>t</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>p</mi><mi>a</mi><mi>t</mi></mrow><mtext mathvariant="monospace">;</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>p</mi><mi>a</mi><mi>t</mi></mrow><mo><mtext mathvariant="monospace"><-</mtext></mo><mrow><mi>e</mi><mi>x</mi><mi>p</mi></mrow><mtext mathvariant="monospace">;</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">let</mtext><mrow><mi>d</mi><mi>e</mi><mi>c</mi><mi>l</mi><mi>s</mi></mrow><mtext mathvariant="monospace">;</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mtext mathvariant="monospace">;</mtext></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rl}
\mathit{lexp} \mathrel{::=} & \text{\texttt{do \{}} \mathit{stmts} \text{\texttt{\}}} \\
\mathit{stmts} \mathrel{::=} & \mathit{stmt}_1 \cdots \mathit{stmt}_n \mathit{exppat} \\
\mathit{stmt} \mathrel{::=} & \mathit{exppat} \text{\texttt{;}} \\
\mid & \mathit{exppat} \mathrel{\text{\texttt{<-}}} \mathit{exp} \text{\texttt{;}} \\
\mid & \text{\texttt{let}} \mathit{decls} \text{\texttt{;}} \\
\mid & \text{\texttt{;}}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:7.2em;vertical-align:-3.35em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">lexp</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">stmts</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">stmt</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord text"><span class="mord texttt">do {</span></span></span><span class="mord"><span class="mord mathit">stmts</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">}</span></span></span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">stmt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">stmt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathit">exppat</span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">exppat</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">exppat</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord text"><span class="mord texttt"><-</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">exp</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord text"><span class="mord texttt">let</span></span></span><span class="mord"><span class="mord mathit">decls</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord text"><span class="mord texttt">;</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>こうしておけば,どの選択肢でも <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>p</mi><mi>a</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">\mathit{exppat}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">exppat</span></span></span></span></span></span> として reduce すれば良くなる為,reduce の衝突が起きなくなる.後は,それぞれの選択肢でパース結果を構成する際,式として解釈したい場所は式で使える構文要素だけかどうか,パターンとして解釈したい場所はパターンで使える構文要素だけかどうかをチェックするというわけだ.しかし,このような工夫が随所に散らばるとかなり文法の保守が面倒なものになり,構文木にも色々細工が必要になってきて結構面倒だ.</p>
<p>個人的に PEG に感じている魅力は,このような涙ぐましい工夫をせずとも,自然に文法を定義してそこから自然なパーサを生成することができ,かなり文法の保守が楽になるという点だ.その上で実用的にはある程度遜色ないパフォーマンスも出るはずという感じだ.実際,Python が最近 PEG パーサに乗り換えたことで有名だが <a class="footnote-reference" href="#pep-0617" id="auto-id-1">[1]</a>,そこでもやはり PEG によるパーサの書きやすさと,それに比べた LL パーサの複雑さと保守管理の手間が主なモチベーションとなっているようだ.</p>
</div>
<div class="section" id="peg">
<h2>先読み付き PEG<a class="headerlink" href="#peg" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ここからが本題.Packrat Parsing はかなり単純と言う話はしたが,この手法多くのメモは不要だし,入力もバックトラックが発生するので全部パースしないと捨てられないしで,実際問題としてメモリ消費の部分は結構杜撰な面がある.Packrat Parsing 提唱論文では遅延評価を利用してその辺うまく GC できるようにする実装も紹介されているが,正直それも本質的にはあまり寄与していないと思う.というのは,例えば以下の文法が与えられることを考えてみよう:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>p</mi><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">{</mtext><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi><mi>s</mi></mrow><mtext mathvariant="monospace">}</mtext></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi><mi>s</mi></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rl}
\mathit{p} \mathrel{::=} &\text{\texttt{\{}} \mathit{stmts} \text{\texttt{\}}} \\
\mid &\mathit{stmts}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathit">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord text"><span class="mord texttt">{</span></span></span><span class="mord"><span class="mord mathit">stmts</span></span><span class="mord text"><span class="mord text"><span class="mord texttt">}</span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">stmts</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{stmts}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord"><span class="mord mathit">stmts</span></span></span></span></span></span> の定義は省略するが,こいつは文の列を表す非終端記号だ.さてこの文法から生成された PEG パーサでは,もしプログラムが <tt class="docutils literal">{</tt> で始まる場合,本質的に入力が全て捨てられない.なぜなら,どっかでバックトラックが発生して一番最初に戻ってくることがあるかもしれないからだ.ただ,もし <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>t</mi><mi>m</mi><mi>t</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{stmts}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord"><span class="mord mathit">stmts</span></span></span></span></span></span> は絶対に <tt class="docutils literal">{</tt> で始まらないように設計されていたとしたら,実際は一番目の選択肢に入った時点で二番目の選択肢は対象外になる.このような場合にも入力を全て保持し続けなければいけないと言うのはかなり微妙だし,それを考慮して注意深く文法を設計するのは PEG を使う動機からして本末転倒だ.</p>
<p>と言うわけで,この節のタイトルに繋がるわけだが,今回作ったライブラリ「ptera」の特徴は,</p>
<ul class="simple">
<li>PEG に先読みを付けてそもそもバックトラックを少なくしてやる</li>
<li>バックトラックが発生する可能性がある地点を予め特定できる実行モデルを考え,適度に入力とメモを GC できるようにする機構を付ける</li>
</ul>
<p>と言う感じ.まずは一つ目の詳細を紹介していく.といっても正規化して一文字先読みつけるだけだが.</p>
<p>ptera では,与えられる PEG 文法を,クラスは変えないがある程度制限された形で受け取る.まず,式を次の形に制限する:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right left right" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi mathvariant="normal">n</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">m</mi></mrow><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mrow><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mn>1</mn></msub><mi mathvariant="normal">/</mi><mo>⋯</mo><mi mathvariant="normal">/</mi><msub><mrow><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mi>n</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>u</mi><mn>1</mn></msub><mo>⋯</mo><msub><mi>u</mi><mi>n</mi></msub></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>≥</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">&</mi><mo stretchy="false">(</mo><msub><mi>u</mi><mn>1</mn></msub><mo>⋯</mo><msub><mi>u</mi><mi>n</mi></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>≥</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">!</mo><mo stretchy="false">(</mo><msub><mi>u</mi><mn>1</mn></msub><mo>⋯</mo><msub><mi>u</mi><mi>n</mi></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>≥</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>u</mi><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>σ</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>σ</mi><mo>∈</mo><mi mathvariant="normal">Σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>A</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>A</mi><mo>∈</mo><mi>N</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rlr}
\mathrm{norm}(e) \mathrel{::=} & \mathit{alt}_1 / \cdots / \mathit{alt}_n \\
\mathit{alt} \mathrel{::=} & u_1 \cdots u_n &(n \geq 0) \\
\mid & \& (u_1 \cdots u_n) &(n \geq 1) \\
\mid & ! (u_1 \cdots u_n) &(n \geq 1) \\
u \mathrel{::=} & \sigma &(\sigma \in \Sigma) \\
\mid & A &(A \in N)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:7.2em;vertical-align:-3.35em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">norm</span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">alt</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">alt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">/</span><span class="mord"><span class="mord"><span class="mord mathit">alt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">&</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mclose">!</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">Σ</span><span class="mclose">)</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>また初期式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mi>S</mi></msub></mrow><annotation encoding="application/x-tex">e_S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は非終端記号でなくてはいけないということにする.元の PEG のクラスと変わっていないことは,気合いで元の PEG からの正規化アルゴリズム書いて,生成言語が同じことを示せばよいが,今回はそこは省略する.さて,ptera はまず,この正規化された PEG 文法の非終端記号に対して,1文字目として許容しうるものを全て計算する.アルゴリズム自体はそこまで難しくなくて,次のような感じ:</p>
<img alt="先読み計算アルゴリズム" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2021/11/peg-parser-generating-by-ptera/peg-parser-generating-by-ptera/lookahead-pseudocode.png"/>
<p>なお,このアルゴリズムが fail する時は,全く文字を消費せずに同じ非終端記号に二度行き着くみたいな時で,つまり無限ループする可能性がある選択肢を含んでいる時.必ずしもその文法が無限ループするとは限らないが,その選択肢を除去しても文法の意味論は変わらないので,ptera ではそのような選択肢を取り除かないとエラーになるようにしている.</p>
<p>後,! (not) の時は先読みを諦めている.基本 not はやってみないと分かんないので,どっちにしろ先読みあんまり効かないケース多いし,そこまで手厚くサポートはしなくてよいかなという感じ.</p>
<p>こんな感じで先読みテーブルを作っておいて,先読み考慮して実行モデルを作ることで,バックトラックが少なくなるし,バックトラックがもう発生しないということも早めに分かるようになる.これにより,バックトラックするかしないかが分かれば,先読みつけない場合より早めにもう必要なくなった入力を解放することができるようになる.</p>
<p>もちろん,今回は1文字先読みしかしてないので,不要なバックトラックが全て事前に取り除けるわけではない.例えば,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>A</mi><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>B</mi><mi mathvariant="normal">/</mi><mi>C</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>B</mi><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>a</mi><mi>b</mi><mi>d</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>C</mi><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>a</mi><mi>c</mi><mi>d</mi></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rl}
A \mathrel{::=} &B / C \\
B \mathrel{::=} & abd \\
C \mathrel{::=} & acd
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">ab</span><span class="mord mathnormal">d</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mord mathnormal">c</span><span class="mord mathnormal">d</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>みたいな文法があった場合,入力が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi>b</mi></mrow><annotation encoding="application/x-tex">ab</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">ab</span></span></span></span></span> で始まっていれば,2文字パースした時点でもうバックトラックが起こらないことが確定する.しかし,今回は1文字しか先読みしていないので,このような場合もバックトラックが起こるものとしてパースは進んでしまう.あんまり深く考えていないが,まず完全にバックトラックが不要になる地点の先読みができるか問題は多分決定不能になる気がする.で,後は効果が良く先読みつける作業が妥当な時間で終わるところを探るという話になる気がするが,一文字先読みは効果が割と期待できアルゴリズムも簡単ということでやっている.ま,つまりあんまり考えてない.そんな感じ.</p>
</div>
<div class="section" id="auto-id-2">
<h2>先読み付き PEG の実行モデル<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,PEG に先読みを付けたはいいが,先読み付き PEG 文法からそのままバックトラック地点を考慮したパーサを直接生成するのは結構めんどくさい.そこで,ptera はパーサを生成する前に SRB というマシンに変換を行う.基本的に LR パーサの生成法にちょっと毛を生やしたようなもので,出力付き状態遷移機械にスタックを伴った意味論を付与するようなマシンになる.</p>
<p>SRB の遷移は,入力文字によりラベル付けされ,出力として以下の操作が指定できる:</p>
<dl class="docutils">
<dt>シフト (<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">s</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">f</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{shift}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">shift</span></span></span></span></span></span>)</dt>
<dd>入力文字を1つ消費し,次の入力文字を見る</dd>
<dt>リデュース (<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">r</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">d</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">c</mi><mi mathvariant="normal">e</mi></mrow><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{reduce}(\mathit{alt})</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">reduce</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">alt</span></span><span class="mclose">)</span></span></span></span></span>)</dt>
<dd>指定された選択肢を元に,スタックから今までのパース結果を取り出しアクションを行う</dd>
<dt>バックポイントの設置 (<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">p</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">b</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">c</mi><mi mathvariant="normal">k</mi></mrow><mo stretchy="false">(</mo><mi>s</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{pushback}(s)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">pushback</span></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span></span>)</dt>
<dd>バックトラック先の状態を伴ったバックポイントを,スタックにプッシュする</dd>
<dt>否定リデュースポイントの設置 (<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">p</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">t</mi></mrow><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{pushnot}(\mathit{alt})</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">pushnot</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">alt</span></span><span class="mclose">)</span></span></span></span></span>)</dt>
<dd>リデュースする否定がついた選択肢を伴ったバックポイントを,スタックにプッシュする</dd>
<dt>エンター (<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">e</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">t</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">r</mi></mrow><mo stretchy="false">(</mo><mi>s</mi><mo separator="true">,</mo><mi>A</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{enter}(s, A)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">enter</span></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mclose">)</span></span></span></span></span>)</dt>
<dd>リデュース後の状態をスタックにプッシュし,非終端記号に対してパースを開始する</dd>
</dl>
<p>状態の集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi></mrow><annotation encoding="application/x-tex">S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span> に対してこれらの操作の集合を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Ω</mi><mo stretchy="false">(</mo><mi>S</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\Omega(S)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">Ω</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></span>,文字列の終端を表す入力文字を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi><mo>∉</mo><mi mathvariant="normal">Σ</mi></mrow><annotation encoding="application/x-tex">\bot \not\in \Sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Σ</span></span></span></span></span> とすると,SRB は状態の集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi></mrow><annotation encoding="application/x-tex">S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span>,入力文字の集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="normal">Σ</mi><mi mathvariant="normal">⊥</mi></msub><mo>=</mo><msub><mi mathvariant="normal">Σ</mi><mi mathvariant="normal">⊥</mi></msub></mrow><annotation encoding="application/x-tex">\Sigma_\bot = \Sigma_\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">⊥</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">⊥</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span>,遷移規則を表す部分関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>=</mo><mi>S</mi><mo>×</mo><msub><mi mathvariant="normal">Σ</mi><mi mathvariant="normal">⊥</mi></msub><mo>⇀</mo><mi mathvariant="normal">Ω</mi><mo stretchy="false">(</mo><mi>S</mi><mo stretchy="false">)</mo><mo>×</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">R = S \times \Sigma_\bot \rightharpoonup \Omega(S) \times S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">⊥</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇀</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">Ω</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span>,初期状態 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>s</mi><mn>0</mn></msub><mo>∈</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">s_0 \in S</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></span> の組で表現される.意味論は以下のようになる:</p>
<img alt="SRB の意味論" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2021/11/peg-parser-generating-by-ptera/peg-parser-generating-by-ptera/srb-semantics.png"/>
<p>受理関数は,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mo stretchy="false">(</mo><mi>S</mi><mo separator="true">,</mo><msub><mi mathvariant="normal">Σ</mi><mi mathvariant="normal">⊥</mi></msub><mo separator="true">,</mo><mi>R</mi><mo separator="true">,</mo><msub><mi>s</mi><mn>0</mn></msub><mo stretchy="false">)</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>=</mo><mo stretchy="false">{</mo><mo stretchy="false">(</mo><mi>x</mi><mo separator="true">,</mo><mi>t</mi><mo stretchy="false">)</mo><mo>∣</mo><mi>x</mi><mo>∈</mo><msup><mi mathvariant="normal">Σ</mi><mo>∗</mo></msup><mo separator="true">,</mo><mi mathvariant="normal">c</mi><mo stretchy="false">⟨</mo><mi mathvariant="normal">∅</mi><mo separator="true">,</mo><mi>ϵ</mi><mo separator="true">,</mo><msub><mi>s</mi><mn>0</mn></msub><mo separator="true">,</mo><mi>x</mi><mi mathvariant="normal">⊥</mi><mo stretchy="false">⟩</mo><msup><mo>→</mo><mo>∗</mo></msup><mi mathvariant="normal">c</mi><mo stretchy="false">⟨</mo><mi>m</mi><mo separator="true">,</mo><mrow><mi mathvariant="normal">a</mi><mi mathvariant="normal">r</mi><mi mathvariant="normal">g</mi></mrow><mo stretchy="false">(</mo><mi>t</mi><mo stretchy="false">)</mo><mo separator="true">,</mo><mi>s</mi><mo separator="true">,</mo><mi mathvariant="normal">⊥</mi><mo stretchy="false">⟩</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\llbracket (S, \Sigma_\bot, R, s_0)\rrbracket = \{(x, t) \mid x \in \Sigma^*, \mathrm{c}\langle \emptyset, \epsilon, s_0, x\bot\rangle \to^* \mathrm{c}\langle m, \mathrm{arg}(t), s, \bot\rangle\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">⊥</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{(</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">c</span><span class="mopen">⟨</span><span class="mord">∅</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ϵ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mord">⊥</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">→</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm">c</span><span class="mopen">⟨</span><span class="mord mathnormal">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm" style="margin-right:0.01389em;">arg</span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">⊥</span><span class="mclose">⟩}</span></span></span></span></span> って感じだ.メタ変数はそれぞれ,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span></span> は packrat parsing 用のメモリ,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ρ</mi></mrow><annotation encoding="application/x-tex">\rho</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span></span></span></span></span> は実行スタック,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> は実行結果の列,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>t</mi></mrow><annotation encoding="application/x-tex">t</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span></span> は実行結果を表す木,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> は入力文字列という感じ.SRB のパースは,3種類の実行状態を持つ:</p>
<dl class="docutils">
<dt>シフト実行 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">c</mi><mo stretchy="false">⟨</mo><mi>m</mi><mo separator="true">,</mo><mi>ρ</mi><mo separator="true">,</mo><mi>s</mi><mo separator="true">,</mo><mi>x</mi><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\mathrm{c}\langle m, \rho, s, x\rangle</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm">c</span><span class="mopen">⟨</span><span class="mord mathnormal">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">⟩</span></span></span></span></span></dt>
<dd>通常の実行状態で,SRB の遷移規則を元に状態を遷移させ,遷移時の出力から実行スタックを操作する</dd>
<dt>リデュース実行 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">r</mi><mo stretchy="false">⟨</mo><mi>m</mi><mo separator="true">,</mo><mi>ρ</mi><mo separator="true">,</mo><mi>α</mi><mo separator="true">,</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mo separator="true">,</mo><mi>x</mi><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\mathrm{r}\langle m, \rho, \alpha, \mathit{alt}, x\rangle</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm">r</span><span class="mopen">⟨</span><span class="mord mathnormal">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">alt</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">⟩</span></span></span></span></span></dt>
<dd>エンターの実行結果を決める操作.今までの実行結果を集めながら,エンターに行き着いたら実行結果を確定し,次のパース実行を始める</dd>
<dt>バック実行 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">f</mi><mo stretchy="false">⟨</mo><mi>m</mi><mo separator="true">,</mo><mi>ρ</mi><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\mathrm{f}\langle m, \rho\rangle</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm" style="margin-right:0.07778em;">f</span><span class="mopen">⟨</span><span class="mord mathnormal">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span></span></span></span></span></dt>
<dd>パース失敗から復帰地点まで戻る.復帰地点に行きあたったら,次のパース実行を始める</dd>
</dl>
<p>これが,この3つの実行状態の頭文字が SRB の名前の由来.否定リデュースポイントは,リデュース実行とバック実行を途中で逆転させるようなものになっている.この SRB を先読み付き PEG に対して,選択肢一つ一つをシフト実行,最後までパースできたらリデュース実行,失敗したらバック実行というように作成し,SRB の意味論に則ってパーサを生成するというのが ptera の残りの処理になる.さて,具体的にどう先読み付き PEG から SRB に変換するかだが,これも LR パーサの状態作成方法から着想を得ていて,アイテムと呼ばれる文法の選択肢とパース位置の組を定義し,基本的にはその集合を1つの状態として変換を行なっていく.具体的なアルゴリズムは,PEG 文法 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>=</mo><mo stretchy="false">(</mo><mi>N</mi><mo separator="true">,</mo><mi mathvariant="normal">Σ</mi><mo separator="true">,</mo><mi>R</mi><mo separator="true">,</mo><msub><mi>A</mi><mn>0</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">G = (N, \Sigma, R, A_0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Σ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span>,先読み関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>L</mi><mo>:</mo><mi>N</mi><mo>→</mo><msup><mn>2</mn><mi mathvariant="normal">Σ</mi></msup></mrow><annotation encoding="application/x-tex">L: N \to 2^\Sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8413em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">Σ</span></span></span></span></span></span></span></span></span></span></span></span>,終端文字 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> に対して,以下の感じになる:</p>
<img alt="先読み付き PEG から SRB への変換" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2021/11/peg-parser-generating-by-ptera/peg-parser-generating-by-ptera/srb-construction.png"/>
<p>ちょっと長いが,</p>
<ol class="arabic simple">
<li>非終端記号に対して,入力文字それぞれに対してエンター遷移先のマップを作る</li>
<li>状態それぞれに対して遷移を作成していく</li>
</ol>
<p>が基本的な流れだ.遷移は,状態に入っている最初の選択肢によって決まる.選択肢のパース位置にあるのが終端記号ならシフト,非終端記号ならエンターを行う.もし,失敗した場合の選択肢があるならその操作を行う前にバックポイントをプッシュしておく.また,バックポイントのプッシュをできる限り少なく,また必要な位置に埋め込む為,他の選択肢でまとめられるものはまとめておく.</p>
<p>正当性は示していないが,成り立つはず:</p>
<dl class="docutils">
<dt>健全性</dt>
<dd>正規化された PEG <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>=</mo><mo stretchy="false">(</mo><mi>N</mi><mo separator="true">,</mo><mi mathvariant="normal">Σ</mi><mo separator="true">,</mo><mi>R</mi><mo separator="true">,</mo><msub><mi>A</mi><mn>0</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">G = (N, \Sigma, R, A_0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Σ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span>,先読み関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>L</mi><mo>=</mo><mrow><mi>L</mi><mi>o</mi><mi>o</mi><mi>k</mi><mi>A</mi><mi>H</mi><mi>e</mi><mi>a</mi><mi>d</mi></mrow><mo stretchy="false">(</mo><mi>G</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">L = \mathit{LookAHead}(G)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">LookAHead</span></span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mclose">)</span></span></span></span></span>,終端文字 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi><mo>∉</mo><mi mathvariant="normal">Σ</mi></mrow><annotation encoding="application/x-tex">\bot \not\in \Sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Σ</span></span></span></span></span>,SRB <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>=</mo><mrow><mi>C</mi><mi>o</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>r</mi><mi>u</mi><mi>c</mi><mi>t</mi><mi>S</mi><mi>R</mi><mi>B</mi></mrow><mo stretchy="false">(</mo><mi>G</mi><mo separator="true">,</mo><mi>L</mi><mo separator="true">,</mo><mi mathvariant="normal">⊥</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">M = \mathit{ConstructSRB}(G, L, \bot)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">ConstructSRB</span></span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">⊥</span><span class="mclose">)</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>G</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>=</mo><mrow><mi mathvariant="normal">d</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mo stretchy="false">(</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>M</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\llbracket G\rrbracket = \mathrm{dom}(\llbracket M\rrbracket)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">G</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">dom</span></span><span class="mopen">(</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mclose">)</span></span></span></span></span> が成り立つ.</dd>
</dl>
<p>ptera ではこれらの変換アルゴリズムを使って,PEG から SRB への変換と SRB の実行器を提供している.</p>
</div>
<div class="section" id="ptera">
<h2>ptera の現状と今後<a class="headerlink" href="#ptera" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>とりあえず,正当性は示していないが ptera は一通り変換と実行器の実装は終えていて,小さい言語で試しにパースしてみて問題なさそうなことも確認した.ただ,現状 ptera を使うにはパースする段階でパーサ生成しないといけない.この後,TemplateHaskell 用の API を作っていく予定で,それが済んだらパーサ生成を TemplateHaskell でやってコンパイル時に事前にパーサが生成できるようになるはずだ.そこまでやったら,一旦 Hackage に上げるかって感じ.その後はあんまり更新の予定はない.</p>
<p>デバッグ情報を出したりする機能は用意していないので,若干使いづらいのとまだバグがありそうという感じがある.多分今後もそれほど真面目にメンテする気はないので,あんまりプロダクション向けではないかなという感じはある.</p>
<p>PEG 自体は色々探求すればまだ面白いことが探せそう.例えば,PEG が他の文法と比べて面白いところとしてエラーハンドリングができるところがある.失敗した時の処理が書けるので,例えば非終端記号ごとにバックトラック先でエラーメッセージをパース結果にすれば,エラーメッセージのカスタマイズとかできたりするのかなあという.後は,Haskell のレイアウトルールパース失敗時の終了処理を,文法として正式に形式化できたりとかの応用が効きそう.時間があったらその辺も考えてみようかなという.とりあえず,備忘録だけ残しておく(結局,備忘録のみになりそうだが).</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,備忘録兼ねて ptera のパーサ生成法を紹介した.ptera では,PEG に先読みつけて,SRB という実行モデルに変換することで,バックトラックを抑えつつ,素の PEG 文法より解析をしやすくしている.</p>
<p>興味があれば触ってみてほしい.後,もっと良い確立手法があればぜひ教えてほしいなあという感じ.では,今回はこれにて.</p>
<table class="docutils footnote" frame="void" id="pep-0617" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td><a class="reference external" href="https://www.python.org/dev/peps/pep-0617">https://www.python.org/dev/peps/pep-0617</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2021/11/peg-parser-generating-by-ptera.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2021/11/peg-parser-generating-by-ptera.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Happy のコンフリクトレポートと向き合う2021-01-31T14:37:38+09:002021-01-31T14:37:38+09:00Mizunashi Manatag:mizunashi-mana.github.io,2021-01-31:/blog/posts/2021/01/how-to-use-happy/<p>Haskell には,Happy と言う名前のパーサジェネレータがある.基本的には,yacc と同じような使い勝手のジェネレータで,GHC で使用 …</p><p>Haskell には,Happy と言う名前のパーサジェネレータがある.基本的には,yacc と同じような使い勝手のジェネレータで,GHC で使用されているため Haskell のパーサジェネレータとしてはそこそこ実績がある.</p>
<p>Happy は意味アクション付き BNF から LALR(1) パーサを生成する.このパーサは基本的に,構文解析表を見ながら shift / reduce と呼ばれる操作を行っていく,shift-reduce パーサの一種になる.しかし,shift-reduce パーサの生成は,一般に BNF から一意に決まらないことがある.そのような BNF が与えられた場合,一般にジェネレータは警告をユーザに伝えつつ,標準的なパーサを出力するようになっていることが多く,Happy もそのようになっている.ただ,その標準的パーサが意図していない動きをする場合も多い.</p>
<p>今回は,Happy が出す警告の見方とその自分なりの解決方法を紹介する.以下の文献を主に参考にしている.</p>
<ul class="simple">
<li><a class="reference external" href="https://www.haskell.org/happy/doc/html/">https://www.haskell.org/happy/doc/html/</a></li>
<li><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/-/blob/eb90d23911ee10868dc2c7cc27a8397f0ae9b41d/compiler/GHC/Parser.y">GHC の Parser.y</a></li>
</ul>
<p>なお、Happy 1.20 を前提に話す。</p>
<div class="section" id="shift-reduce">
<h2>shift-reduce パーサ<a class="headerlink" href="#shift-reduce" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まずは shift-reduce パーサの簡単な動きを押さえておく.shift-reduce パーサと言っても,その解析方法や実装によって結構生成方法が違うが,今回は LALR(1) に焦点を当てる.今回はそこまで細かい話には立ち入らないので,大まかなイメージをつかんでもらえれば良い.</p>
<p>shift-reduce パーサは,その名の通り,</p>
<dl class="docutils">
<dt>shift</dt>
<dd>入力から1つ文字を持ってきて,葉を作ってスタックに入れる</dd>
<dt>reduce</dt>
<dd>スタックから幾つか木を持ってきて,それを組み合わせた木を作りスタックに入れる</dd>
</dl>
<p>の2つの操作を繰り返しながら,パースを行うボトムアップ構文解析法を指す.動きのイメージは <a class="reference external" href="https://en.wikipedia.org/wiki/Shift-reduce_parser">https://en.wikipedia.org/wiki/Shift-reduce_parser</a> に割とわかりやすい表があるので,ちょっと拝借する.</p>
<pre class="literal-block">
R1: assign ← ID '=' sums
R2: sums ← sums '+' prods
R3: sums ← prods
R4: prods ← prods '*' value
R5: prods ← value
R6: value ← INT
R7: value ← ID
</pre>
<p>という文法があるとする.大文字や <tt class="docutils literal"><span class="pre">'..'</span></tt> が終端記号,小文字で書かれたものが非終端記号だ.この文法から生成されるパーサは,だいたい以下のような動きをする:</p>
<table border="1" class="docutils">
<colgroup>
<col width="40%"/>
<col width="14%"/>
<col width="24%"/>
<col width="22%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">パーススタック</th>
<th class="head">先読み</th>
<th class="head">残りの入力</th>
<th class="head">操作</th>
</tr>
</thead>
<tbody valign="top">
<tr><td><tt class="docutils literal">ID</tt></td>
<td><tt class="docutils literal">=</tt></td>
<td><tt class="docutils literal">ID + ID * INT</tt></td>
<td>shift</td>
</tr>
<tr><td><tt class="docutils literal">ID =</tt></td>
<td><tt class="docutils literal">ID</tt></td>
<td><tt class="docutils literal">+ ID * INT</tt></td>
<td>shift</td>
</tr>
<tr><td><tt class="docutils literal">ID = ID</tt></td>
<td><tt class="docutils literal">+</tt></td>
<td><tt class="docutils literal">ID * INT</tt></td>
<td>reduce by (R7)</td>
</tr>
<tr><td><tt class="docutils literal">ID = value</tt></td>
<td><tt class="docutils literal">+</tt></td>
<td><tt class="docutils literal">ID * INT</tt></td>
<td>reduce by (R5)</td>
</tr>
<tr><td><tt class="docutils literal">ID = prods</tt></td>
<td><tt class="docutils literal">+</tt></td>
<td><tt class="docutils literal">ID * INT</tt></td>
<td>reduce by (R3)</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums</tt></td>
<td><tt class="docutils literal">+</tt></td>
<td><tt class="docutils literal">ID * INT</tt></td>
<td>shift</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums +</tt></td>
<td><tt class="docutils literal">ID</tt></td>
<td><tt class="docutils literal">* INT</tt></td>
<td>shift</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums + ID</tt></td>
<td><tt class="docutils literal">*</tt></td>
<td><tt class="docutils literal">INT</tt></td>
<td>reduce by (R7)</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums + value</tt></td>
<td><tt class="docutils literal">*</tt></td>
<td><tt class="docutils literal">INT</tt></td>
<td>reduce by (R5)</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums + prods</tt></td>
<td><tt class="docutils literal">*</tt></td>
<td><tt class="docutils literal">INT</tt></td>
<td>shift</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums + prods *</tt></td>
<td><tt class="docutils literal">INT</tt></td>
<td> </td>
<td>shift</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums + prods * INT</tt></td>
<td> </td>
<td> </td>
<td>reduce by (R7)</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums + prods * value</tt></td>
<td> </td>
<td> </td>
<td>reduce by (R5)</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums + prods</tt></td>
<td> </td>
<td> </td>
<td>reduce by (R2)</td>
</tr>
<tr><td><tt class="docutils literal">ID = sums</tt></td>
<td> </td>
<td> </td>
<td>reduce by (R1)</td>
</tr>
<tr><td><tt class="docutils literal">assign</tt></td>
<td> </td>
<td> </td>
<td>accept</td>
</tr>
</tbody>
</table>
<p>パーサは状態スタックを持っており、次にどういう操作を行うかは、先読み一文字とパーススタックの先頭要素、現在の状態から決まる。</p>
</div>
<div class="section" id="auto-id-1">
<h2>Happy でパーサを記述する<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>実際に Happy で shift-reduce パーサを生成し、どういう状態と操作が行われるかを見てみる。</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">-- Parser.y</span>
<span class="p">{</span>
<span class="kr">module</span><span class="w"> </span><span class="nn">Parser</span><span class="w"> </span><span class="kr">where</span>
<span class="p">}</span>
<span class="o">%</span><span class="n">token</span>
<span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">TokId</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">INT</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">TokInt</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sc">'='</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">TokSym</span><span class="w"> </span><span class="s">"="</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">TokSym</span><span class="w"> </span><span class="s">"+"</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sc">'*'</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">TokSym</span><span class="w"> </span><span class="s">"*"</span><span class="w"> </span><span class="p">}</span>
<span class="o">%</span><span class="n">tokentype</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Token</span><span class="w"> </span><span class="p">}</span>
<span class="o">%</span><span class="n">name</span><span class="w"> </span><span class="n">assign</span>
<span class="o">%%</span>
<span class="nf">assign</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="kt">Token</span><span class="p">,</span><span class="w"> </span><span class="kt">Expr</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="sc">'='</span><span class="w"> </span><span class="n">sums</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="o">$</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
<span class="nf">sums</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">sums</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">prods</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">prods</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
<span class="nf">prods</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">prods</span><span class="w"> </span><span class="sc">'*'</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Prod</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
<span class="nf">value</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">INT</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
<span class="p">{</span>
<span class="nf">happyError</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Token</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">happyError</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="ne">error</span><span class="w"> </span><span class="s">"happyError"</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Token</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">TokId</span><span class="w"> </span><span class="kt">String</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">TokInt</span><span class="w"> </span><span class="kt">Integer</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">TokSym</span><span class="w"> </span><span class="kt">String</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="p">(</span><span class="kt">Eq</span><span class="p">,</span><span class="w"> </span><span class="kt">Show</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Prod</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="kt">Token</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="p">(</span><span class="kt">Eq</span><span class="p">,</span><span class="w"> </span><span class="kt">Show</span><span class="p">)</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>このプログラムに対して、</p>
<pre class="literal-block">
happy -i Parser.y
</pre>
<p>を実行すると、パーサプログラム <tt class="docutils literal">Parser.hs</tt> とパーサ生成時の情報 <tt class="docutils literal">Parser.info</tt> が生成される。<tt class="docutils literal">Parser.info</tt> には文法解析時の情報と、状態遷移に関するものが書かれる。状態遷移に関するものは <tt class="docutils literal">States</tt> 節に書かれている。今回は、</p>
<pre class="literal-block">
-----------------------------------------------------------------------------
States
-----------------------------------------------------------------------------
State 0
ID shift, and enter state 2
assign goto state 3
State 1
ID shift, and enter state 2
State 2
assign -> ID . '=' sums (rule 1)
'=' shift, and enter state 4
State 3
%start_parseAssign -> assign . (rule 0)
%eof accept
State 4
assign -> ID '=' . sums (rule 1)
ID shift, and enter state 8
INT shift, and enter state 9
sums goto state 5
prods goto state 6
value goto state 7
State 5
assign -> ID '=' sums . (rule 1)
sums -> sums . '+' prods (rule 2)
'+' shift, and enter state 11
%eof reduce using rule 1
State 6
sums -> prods . (rule 3)
prods -> prods . '*' value (rule 4)
'+' reduce using rule 3
'*' shift, and enter state 10
%eof reduce using rule 3
...
</pre>
<p>みたいな情報が出力される.それぞれの状態について,</p>
<ul class="simple">
<li>State の値</li>
<li>reduce 途中の規則</li>
<li>先読み値での操作</li>
<li>パーススタックの状態による操作</li>
</ul>
<p>が表示されている.reduce 途中の規則表示は,<tt class="docutils literal">.</tt> の位置までは reduce 済みということを表している.この辺は LALR 法に馴染みのある人なら分かると思うが,状態の作り方に由来する情報で,解析するプログラムが大きくなるとあまり役に立つ情報ではなかったりするが,覚えておいて損はないだろう.</p>
</div>
<div class="section" id="auto-id-2">
<h2>コンフリクトとその解決<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,ここからが本題.shift-reduce パーサ生成では,パーサが上記の通りの動きをすることから,先読みしている文字から shift か reduce のどちらを行うか一意に決めなければならない.しかし,書かれた文法によっては,うまく一意に決められないことがある.大方問題になるのは以下のケースだ:</p>
<ul class="simple">
<li>文法が曖昧性を含んでいる</li>
<li>先をパースして見なければ,操作が決定できない</li>
</ul>
<p>一般的に,shift-reduce パーサ生成器はこのような問題を直接検出はしてくれない場合が多い.特に,Happy の場合は,直接検出の機能はない.ただ代わりに,これらの問題は間接的に shift/reduce 衝突,reduce/reduce 衝突という2つの警告によって報告される.</p>
<p>それぞれの警告は,名前の通り</p>
<dl class="docutils">
<dt>shift/reduce 衝突</dt>
<dd>shift 操作と reduce 操作,どちらも可能.この場合,自動的に shift 操作が選択される.</dd>
<dt>reduce/reduce 衝突</dt>
<dd>可能な reduce 操作が複数ある.この場合,自動的に一番早く現れる規則に関する reduce 操作が選択される.</dd>
</dl>
<p>という問題を表している.実際に,衝突が報告されるようなプログラムを書いてみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">-- Parser.y</span>
<span class="p">{</span>
<span class="kr">module</span><span class="w"> </span><span class="nn">Parser</span><span class="w"> </span><span class="kr">where</span>
<span class="p">}</span>
<span class="o">%</span><span class="n">token</span>
<span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">TokId</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">TokSym</span><span class="w"> </span><span class="s">"+"</span><span class="w"> </span><span class="p">}</span>
<span class="o">%</span><span class="n">tokentype</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Token</span><span class="w"> </span><span class="p">}</span>
<span class="o">%</span><span class="n">name</span><span class="w"> </span><span class="n">expr</span>
<span class="o">%%</span>
<span class="nf">expr</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
<span class="p">{</span>
<span class="nf">happyError</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Token</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">happyError</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="ne">error</span><span class="w"> </span><span class="s">"happyError"</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Token</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">TokId</span><span class="w"> </span><span class="kt">String</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">TokSym</span><span class="w"> </span><span class="kt">String</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="p">(</span><span class="kt">Eq</span><span class="p">,</span><span class="w"> </span><span class="kt">Show</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="kt">Token</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="p">(</span><span class="kt">Eq</span><span class="p">,</span><span class="w"> </span><span class="kt">Show</span><span class="p">)</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>これの <tt class="docutils literal">Parser.info</tt> を見ると,最初に</p>
<pre class="literal-block">
state 6 contains 1 shift/reduce conflicts.
</pre>
<p>というように shift/reduce 衝突が報告される.State 6 の情報を見に行ってみると,</p>
<pre class="literal-block">
State 6
expr -> expr . '+' expr (rule 1)
expr -> expr '+' expr . (rule 1)
'+' shift, and enter state 5
(reduce using rule 1)
%eof reduce using rule 1
</pre>
<p>という表示がある.<tt class="docutils literal">'+'</tt> の操作で <tt class="docutils literal">(reduce using rule 1)</tt> と言う表記があるのが分かるだろう.衝突している操作で,選ばれなかったものは <tt class="docutils literal"><span class="pre">(...)</span></tt> と言う形で表記される.今回の場合は,</p>
<ul class="simple">
<li><tt class="docutils literal">shift, and enter state 5</tt></li>
<li><tt class="docutils literal">reduce using rule 1</tt></li>
</ul>
<p>が衝突し,shift/reduce 衝突なので shift が優先されている.このケースは文法自体に曖昧性がある.つまり,<tt class="docutils literal">a + b + c</tt> のような式が,<tt class="docutils literal">Sum (Sum a b) c</tt> とパースされて欲しいのか,<tt class="docutils literal">Sum a (Sum b c)</tt> とパースされて欲しいのか分からないのだ.<tt class="docutils literal">'+'</tt> が出てきた時に shift を優先させると,shift を貪欲的に行い最終的にまとめて reduce されるため <tt class="docutils literal">Sum a (Sum b c)</tt> が結果になる.実際,今回のパース結果を見てみると,</p>
<pre class="literal-block">
>>> expr [TokId "a", TokSym "+", TokId "b", TokSym "+", TokId "c"]
Sum (Val (TokId "a")) (Sum (Val (TokId "b")) (Val (TokId "c")))
</pre>
<p>となっている.reduce が優先された場合,まず出来上がったところから reduce していくため,<tt class="docutils literal">Sum (Sum a b) c</tt> が結果になる.もし,shift 優先で問題ないなら,それを Happy に <tt class="docutils literal">%shift</tt> ディレクティブで以下のように教えることができる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">expr</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="o">%</span><span class="n">shift</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>または,文法から曖昧性を排除することで,解決できる.こちらの方が一般的な解決方法だろう.左結合でのパース結果,つまり reduce 優先した場合の結果が得たかったら次のように書けば良い:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">expr</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">(</span><span class="kt">Val</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>shift/reduce 衝突は基本避けられるなら避けた方がいいが,そこまで無理をして避ける必要はないだろう.shift/reduce を無理に避けるため文法が複雑になるより,<tt class="docutils literal">%shift</tt> ディレクティブを指定した方がプログラムが保守しやすい場合も多い.特に,演算子・ブロックの優先順位の問題においては,<tt class="docutils literal">%shift</tt> ディレクティブや <tt class="docutils literal">%left</tt>,<tt class="docutils literal">%right</tt> を使用した方が意味アクションが書きやすい場合が多い.</p>
<p>しかしながら,reduce/reduce 衝突の方は,プログラマが意図しないパーサが生成されるケースが多いため,注意が必要だ.例えば問題になるのは,以下のような文法だ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">expr</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
<span class="nf">value</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>この文法では,</p>
<pre class="literal-block">
state 10 contains 1 reduce/reduce conflicts.
</pre>
<p>という警告が生成される.State 10 は次のような情報表示がされる:</p>
<pre class="literal-block">
State 10
expr -> value . '+' value (rule 1)
expr -> value '+' value . (rule 1)
expr -> value . '+' expr (rule 2)
expr -> value . (rule 3)
'+' shift, and enter state 6
%eof reduce using rule 3
(reduce using rule 1)
</pre>
<p>この場合,<tt class="docutils literal">a + b</tt> という式を,</p>
<ul class="simple">
<li><tt class="docutils literal">expr <span class="pre">-></span> value '+' expr</tt> の規則で reduce するか</li>
<li><tt class="docutils literal">expr <span class="pre">-></span> value '+' value</tt> の規則で reduce するか</li>
</ul>
<p>が分からない点で,文法が曖昧になっている.ただ,警告自体は,</p>
<ul class="simple">
<li><tt class="docutils literal">expr <span class="pre">-></span> value '+' value</tt></li>
<li><tt class="docutils literal">expr <span class="pre">-></span> value</tt></li>
</ul>
<p>の2つが衝突していると言っている事には注意が必要だ.実際には,後者のルールは reduce が起きた後 <tt class="docutils literal">expr <span class="pre">-></span> value '+' expr</tt> で reduce が走ることを前提にしているわけだが,警告をそのまま素直に受け取ると,問題の特定が難しい場合があるのには注意だ.さて,今回のケースでは2つの reduce が被らないように文法を修正するのが良いだろう.具体的には,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">expr</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">expr2</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
<span class="nf">expr2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="sc">'+'</span><span class="w"> </span><span class="n">expr2</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Sum</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="o">$</span><span class="mi">3</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
<span class="nf">value</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="kt">ID</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Val</span><span class="w"> </span><span class="o">$</span><span class="mi">1</span><span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>というように修正するのが良いだろう.</p>
<p>基本的に,自身が管理できていない衝突は,その原因を特定して解決しておいた方がいい.特に,reduce/reduce 衝突は解決しておく必要があるだろう.Happy はデフォルトでは衝突を検知してもパーサをそのまま生成するが,このようなマナーを考慮して,<tt class="docutils literal">%expect</tt> ディレクティブというものを用意してくれている.これを使って,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">%</span><span class="n">expect</span><span class="w"> </span><span class="mi">10</span>
</pre></div></td></tr></table></div>
<p>というように書くと,reduce/shift 衝突が 10 箇所,reduce/reduce 衝突がない場合のみパーサを生成するようになる.基本的に,reduce/shift 衝突は,その起こっている箇所に <tt class="docutils literal">%shift</tt> ディレクティブを指定するのがいいだろう.なので,基本的に,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">%</span><span class="n">expect</span><span class="w"> </span><span class="mi">0</span>
</pre></div></td></tr></table></div>
<p>を指定し,<tt class="docutils literal">%shift</tt> ディレクティブを適宜入れながら,reduce/reduce 衝突は回避していくのが良いだろう.</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今回は shift-reduce 生成器 Happy で起こる shift/reduce 衝突,reduce/reduce 衝突の回避方法を軽く紹介した.基本的に,衝突は回避していくのが良いが,shift/reduce 衝突については無理に回避せず <tt class="docutils literal">%shift</tt> を使うという手がある.また,<tt class="docutils literal">%expect 0</tt> はつけておいた方が良いだろう.</p>
<p>文法が大きくなってくると,State の情報で提示された reduce の対象ルールと実際問題がある曖昧性のあるルールは割とかけ離れていたりするので注意が必要だ.基本的には,先読み対象のトークンが使われている場所を探索し,地道に曖昧性がある部分を探していくしかないと思う.また,実際には先読みを十分に行えば判別可能な曖昧性についても,衝突を起こしてしまう場合がある.その場合は,効率的なパースのためにも早期に判別可能な文法に修正していくのが良いだろう.この辺は,PEG とかと比べると少々使い勝手悪いっすね.というわけで,今日はこの辺で.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2021/01/how-to-use-happy.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2021/01/how-to-use-happy.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Unicode とサロゲートコードポイント2020-11-14T10:48:12+09:002020-11-14T11:12:49+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-11-14:/blog/posts/2020/11/unicode-surrogate-codepoint/<p>Unicode は、文字コードの標準を目指して創設された規格であり、文字をどう処理するか、テキストデータとしてどう表すか …</p><p>Unicode は、文字コードの標準を目指して創設された規格であり、文字をどう処理するか、テキストデータとしてどう表すかを規定している。今や国際的に普及した規格で、特に Unicode が規定する符号化方式 UTF-8 は、いまやテキストデータのエンコーディングデファクト標準となっている。</p>
<p>Unicode は歴史的経緯からサロゲートコードポイントという仕様を包含している。今回は、この仕様の紹介と、UTF-8 を使う際の注意点を見ていく。なお,</p>
<ul class="simple">
<li>Unicode 13.0.0: <a class="reference external" href="https://www.unicode.org/versions/Unicode13.0.0/">https://www.unicode.org/versions/Unicode13.0.0/</a></li>
</ul>
<p>を元にしていく.</p>
<div class="section" id="auto-id-1">
<h2>Unicode と固定長の夢<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>当初、Unicode は ASC-II の固定長 7bit 表現に倣い、固定長 16bit で世界中の文字を表現する規格として提案された。当時の提案 <a class="footnote-reference" href="#unicode-88" id="auto-id-2">[1]</a> では、</p>
<blockquote>
<p>In the Unicode system, a simple unambiguous fixed-length character encoding is integrated into a coherent overall architecture of text processing.</p>
<p>Unicode システムでは,単純で明確な固定長の文字コードによって,全ての文書処理においての一貫性が提供されます.</p>
</blockquote>
<p>が、Unicode の売り文句だった。つまり,文字一つ一つに 16bit の中からコードを割り当てることで,世界中の文字を表そうとしたのだ.このコンセプト自体は、現在の Unicode でも引き継がれているが、残念ながら今や Unicode は固定長ではなくなってしまった。Unicode の文字列において,長さとは何かというのは,また色々とややこしい話になるので,とりあえず置いておく.</p>
<p>さて,当初 16bit,つまり 65536 文字で世界中の文字を納めようという計画は,CJK (Chinese / Japanese / Korean) 圏の参戦で見事に頓挫することになる.文字の登録件数は,Unicode 1.0 <a class="footnote-reference" href="#unicode-1-0" id="auto-id-3">[2]</a> の時点で28706 件だったのが,Unicode 4.0 <a class="footnote-reference" href="#unicode-4-0" id="auto-id-4">[3]</a> では 96382 件まで膨れ上がることになる.Unicode 4.0 の数字から分かる通り,65536 文字を明に超える.Unicode は,2.0 から 16bit 固定長で全ての文字を収容することを諦め,以降 3.0 からは本格的に 21bit 体制に移行していくことになる.</p>
<p>さて,21bit 体制に移行する時に問題となったのが,それまで使っていたエンコーディング方法だ.Unicode はそれまで 16bit 前提の世界で,割り当てられた文字をそのまま 2byte 固定表現でエンコーディングする方法をとっていた.しかし,文字が 16bit に収まらなくなってしまった今,そのエンコーディングで全ての文字を表すことはできない.そこで Unicode は固定表現を諦め,それまでの互換性を保ったまま可変長の文字表現を導入することとなる.</p>
<p>こうして最初に掲げられた Unicode の標語は,仕様から姿を消すことになった.</p>
</div>
<div class="section" id="utf-16">
<h2>UTF-16 とサロゲートペア<a class="headerlink" href="#utf-16" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ところで,なぜ 21bit という中途半端なビット数を採用することにしたのだろうか? その話に入る前に,Unicode の簡単な概要を述べておく.</p>
<p>Unicode は扱える文字一つ一つにコードポイント (code point) と呼ばれる符号を割り当てている.符号は <tt class="docutils literal">0</tt> から <tt class="docutils literal">0x10FFFF</tt> (1,114,111) の間から採用される.つまり,その空間に入る文字数しか Unicode は扱えない.ついでに,21bit 最高値は <tt class="docutils literal">0x1FFFFF</tt> なので,厳密に 21bit 空間がフルに使えるわけではない.この数は</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mn>0</mn><mi mathvariant="normal">x</mi><mi mathvariant="normal">F</mi><mi mathvariant="normal">F</mi><mi mathvariant="normal">F</mi><mi mathvariant="normal">F</mi></mrow><mo>+</mo><msup><mrow><mn>0</mn><mi mathvariant="normal">x</mi><mn>400</mn></mrow><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">
\mathrm{0xFFFF} + \mathrm{0x400} ^ 2
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathrm">0xFFFF</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">0x400</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></span></div>
<p>という計算式によって得られる.この <tt class="docutils literal">0x400</tt> という数はサロゲート領域と呼ばれるコードポイント空間のサイズ (の 2 分の 1) からくる.</p>
<p>実は,Unicode のコードポイント,つまり <tt class="docutils literal">0</tt> から <tt class="docutils literal">0x10FFFF</tt> までの数は,全てが文字を割り当てられることを想定されているわけではない.文字を割り当てるコードポイントは,通常のコードポイントと区別して,Unicode ではスカラー値 (Unicode scalar value) と呼ばれている.正確な Unicode スカラー値の定義は,サロゲート領域に含まれないコードポイントのことだ.サロゲート領域とは,<tt class="docutils literal">0xD800</tt> から <tt class="docutils literal">0xDFFF</tt> のコードポイント空間を指し,この空間の値には文字は割り当てられない.よって,Unicode スカラー値とは,それ以外の <tt class="docutils literal">0</tt> から <tt class="docutils literal">0x10FFFF</tt> の間の値のことということになる.この微妙な位置に領域が空いているのは,Unicode コードポイントとして何か特別な使用方法を意図してのものではなく,テキストデータへのエンコーディングを見据えてのものになる.</p>
<p>Unicode が初期,16bit 固定長の夢を描いており,それが途中で破綻したことは上で説明した.しかし,破綻したからといって,では今から 16bit による文字表現はやめますと言っても,全ての処理系がはいそうですかと応じられるわけではなかった.特に,文字表現はほぼ根幹となるようなデータ型であり,それが 16bit 固定になっていた場合,そのサイズを変えるのは容易なことではない.そこで,Unicode は 16bit 固定長の夢を諦めても,テキストデータの表現において処理するデータの単位 (これをコードユニットと言う) を 16bit から変えるわけにはいかない.さらに,それまで搭載していた文字については,今までのテキストデータと互換する必要がある.つまり,今まで 16bit で一つの文字を表していたものについては,コードポイントをそのまま 16bit で表した数値を一つのコードユニットとして扱い,かつ 16bit に収まらないコードポイントを持つ文字は,何とかして 16bit 単位のデータとして表現しなければいけない.もちろん,16bit を超えるコードポイントを持つ文字は,16bit 2つ分に分割して表現するという方法が取れるが,その場合デコーディングの方法が一意に定まらなくなってしまう.つまり,コードポイント <tt class="docutils literal">0x1f34e</tt> の文字を,</p>
<pre class="literal-block">
0x0001 0xf34e
</pre>
<p>とエンコードした場合,デコードする際 <tt class="docutils literal">0x1</tt>,<tt class="docutils literal">0xf34e</tt> それぞれのコードポイントに対応する文字 2 つにデコードするか,<tt class="docutils literal">0x1f34e</tt> のコードポイントに対応する文字 1 つにデコードするかが決められなくなるのだ.</p>
<p>こうなってしまっては仕方ないため,Unicode は,それまで使用していなかった領域を特別にサロゲート領域として指定し,そこのコードポイントには文字は割り当てないことにした.そして,そこの範囲で何とか 16bit のコードユニットになるよう頑張る方法を考えることにした.この方法の利点は,</p>
<ul class="simple">
<li>16bit を超えないコードポイントを持つ文字については,影響を受けない</li>
<li>それまでコードポイント1つを単純にコードユニット1つとして扱っていた実装は,コードユニット2つ分の文字は扱えないとすることでそれまでの処理を継続できる</li>
</ul>
<p>というところにある.後は,デコードが一意に定まるようなエンコード / デコード方法を考えられれば良い.結果的に Unicode が採用したのは</p>
<ol class="arabic simple">
<li>コードポイントの内,<tt class="docutils literal">0xD800 - 0xDBFF</tt> (<tt class="docutils literal"><span class="pre">0b110110??????????</span></tt>) を high surrogate,<tt class="docutils literal">0xDC00 - 0xDFFF</tt> (<tt class="docutils literal"><span class="pre">0b110111??????????</span></tt>) を low surrogate という名の領域として確保し,そこは文字を割り当てないようにする</li>
<li><tt class="docutils literal">0x10000 - 0x10FFFF</tt> のコードポイントは,<tt class="docutils literal">0x10000</tt> を引き (つまり,<tt class="docutils literal">0x00000 - 0xFFFFF</tt> の 20bit 値になる),10bit の値を表すコードユニット 2 つとして扱う</li>
<li>コードユニットの値は,上位 10bit は <tt class="docutils literal">0xD800</tt> を足して high surrogate のコードポイントになるように,下位 10bit は <tt class="docutils literal">0xDC00</tt> を足して low surrogate に収まるようにする</li>
</ol>
<p>という方法になる.この方法が俗に言う UTF-16 と呼ばれるエンコーディング方法である.コードユニット 2 つになる場合は,high / low surrogate は区別できるため,連結さえしていれば順不同で保存できるが,デフォルトではビッグエンディアン,つまり high の次に low という順で保存することが決められている <a class="footnote-reference" href="#utf-16-endian-variation" id="auto-id-5">[4]</a>.</p>
<p>Unicode で格納できる文字が中途半端な上限を持っているのは,UTF-16 で表現できる値の上限で設定されているからである.</p>
</div>
<div class="section" id="pep-383">
<h2>PEP 383<a class="headerlink" href="#pep-383" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,UTF-16 の互換性のため,Unicode のコードポイントには文字の割り当てが避けられてる領域があった.この領域はもちろん,Unicode scalar value ではないので,エンコードの対象ではない.</p>
<p>ところで,プログラミング言語には,文字列の内部表現のシェアが大きく分かれている.大きくは,</p>
<ul class="simple">
<li>UTF-8 / UTF-16 / UTF-32 のいずれかを内部表現として使っている言語</li>
<li>Unicode コードポイントの列を内部表現として使っている言語</li>
</ul>
<p>に分かれている.個人的に観測している範囲では,古い言語は UTF-16 の採用率が高く,最近は UTF-8 の採用率が高い気がする.古い言語で UTF-16 採用率が高いのは,やはり Unicode の歴史的事情が大きく影響を与えているんじゃないだろうか? まあ,その辺の話は置いておいて,今回注目したいのが「Unicode コードポイントの列を内部表現として使っている言語」だ.例としては,Python,Haskell <a class="footnote-reference" href="#ghc-haskell" id="auto-id-6">[5]</a> が相当する.</p>
<p>Unicode コードポイントの列というのは,つまりは <tt class="docutils literal">0</tt> から <tt class="docutils literal">0x10FFFF</tt> の間の整数の列ということだ.ところが,コードポイントにはサロゲートコードポイントが含まれているため,文字表現として実質必要なのは <tt class="docutils literal">0</tt> から <tt class="docutils literal">0xD7FF</tt>,<tt class="docutils literal">0xE000</tt> から <tt class="docutils literal">0x10FFFF</tt> の数値だけだ.なので,<tt class="docutils literal">0xD800</tt> から <tt class="docutils literal">0xDFFF</tt> の間は使われない領域ということになる.こういう領域を見ると有効活用したいと思うのがエンジニアの性らしく,Python / Haskell ではそれぞれが,実は微妙に Unicode コードポイントから拡張を施している.これらの言語では,コードポイントのうち,<tt class="docutils literal">0xDC80</tt> から <tt class="docutils literal">0xDCFF</tt> の数値は Unicode コードポイントして扱われない場合がある.</p>
<p>では,何に使われているかというと,ASCII 互換の文字コードでエンコードされたバイト列に対し,デコードに失敗した文字を表現するために使われる.正直こんな機能あまり出番はないと思うというか,使いたくなるユースケースはあまり思い浮かばないが,例えばこの機能によって文字列型でバイト列を扱うことができる.何を言ってるか分からないと思うので,とりあえず Python3 で例を見てみよう:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">>>></span> <span class="sa">b</span><span class="s1">'ab</span><span class="se">\xe3\x81</span><span class="s1">'</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">)</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s2">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="ne">UnicodeDecodeError</span><span class="p">:</span> <span class="s1">'ascii'</span> <span class="n">codec</span> <span class="n">can</span><span class="s1">'t decode byte 0xe3 in position 2: ordinal not in range(128)</span>
<span class="o">>>></span> <span class="sa">b</span><span class="s1">'ab</span><span class="se">\xe3\x81</span><span class="s1">'</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">,</span> <span class="s1">'surrogateescape'</span><span class="p">)</span>
<span class="s1">'ab</span><span class="se">\udce3\udc81</span><span class="s1">'</span>
<span class="o">>>></span> <span class="sa">b</span><span class="s1">'ab</span><span class="se">\xe3\x81</span><span class="s1">'</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">,</span> <span class="s1">'surrogateescape'</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">,</span> <span class="s1">'surrogateescape'</span><span class="p">)</span>
<span class="sa">b</span><span class="s1">'ab</span><span class="se">\xe3\x81</span><span class="s1">'</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">b'ab\xe3\x81'</tt> というバイト列の <tt class="docutils literal">\xe3</tt>,<tt class="docutils literal">\x81</tt> は,それぞれが <tt class="docutils literal">0x7F</tt> を超える値なため,ASCII では文字が割り当てられていない.そのため,もちろん ASCII エンコーディングでデコードしようとすると失敗する.ところが,<tt class="docutils literal">surrogateescape</tt> というエンコーディングモードを使うと,このバイト列はデコードでき,サロゲートコードポイントを含む文字列が生成されることになる.Python の <tt class="docutils literal">surrogateescape</tt> は次のようなことを行うモードだ:</p>
<dl class="docutils">
<dt>デコード時</dt>
<dd><ol class="first last arabic simple">
<li>バイト列が正しくデコードできるならデコードする</li>
<li><dl class="first docutils">
<dt>正しくデコードできないバイト <tt class="docutils literal">c</tt> に出会すと,</dt>
<dd><ul class="first last">
<li><tt class="docutils literal">c >= 0x80</tt> ならば,コードポイント <tt class="docutils literal">0xDC00 + c</tt> にデコードする</li>
<li><tt class="docutils literal">c < 0x80</tt> ならば,デコードに失敗する</li>
</ul>
</dd>
</dl>
</li>
</ol>
</dd>
<dt>エンコード時</dt>
<dd><ol class="first last arabic simple">
<li><tt class="docutils literal">0xDC80</tt> から <tt class="docutils literal">0xDCFF</tt> の範囲の文字 <tt class="docutils literal">c</tt> は,<tt class="docutils literal">c - 0xDC00</tt> に相当するバイトを出力する</li>
<li>それ以外の文字はそのままエンコードする</li>
</ol>
</dd>
</dl>
<p><tt class="docutils literal">c < 0x80</tt> の時デコードに失敗するのが,ASCII 互換でない文字コードに対応できない理由だ <a class="footnote-reference" href="#utf-16-surrogateescape" id="auto-id-7">[6]</a>.この仕様は,<a class="reference external" href="https://www.python.org/dev/peps/pep-0383/">PEP 383</a> で決まっている.なお,技術的には <tt class="docutils literal">c < 0x80</tt> かどうかの分岐は取り除けるが,セキュリティリスクを軽減するためにこうなっているようだ <a class="footnote-reference" href="#pep383-security-risk" id="auto-id-9">[7]</a>.とにかくこれにより,メモリ効率的にはだいぶ無駄ではあるが,文字列としてバイト列をそのまま扱えるようにできたりする.</p>
<p>Haskell も <a class="reference external" href="https://www.python.org/dev/peps/pep-0383/">PEP 383</a> と大体同じ方式のエンコーディングモードを搭載している.こちらは <tt class="docutils literal">Roundtrip</tt> モードという名前になっている.実際に試してみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">>>></span><span class="w"> </span><span class="kr">import</span><span class="w"> </span><span class="nn">System.IO</span>
<span class="o">>>></span><span class="w"> </span><span class="kr">import</span><span class="w"> </span><span class="nn">GHC.IO.Encoding.Latin1</span>
<span class="o">>>></span><span class="w"> </span><span class="kr">import</span><span class="w"> </span><span class="nn">GHC.IO.Encoding.Failure</span>
<span class="o">>>></span><span class="w"> </span><span class="n">ascii</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">mkAscii</span><span class="w"> </span><span class="kt">RoundtripFailure</span>
<span class="o">>>></span><span class="w"> </span><span class="n">openFile</span><span class="w"> </span><span class="s">"sample.txt"</span><span class="w"> </span><span class="kt">ReadWriteMode</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="nf">\</span><span class="n">h</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">hSetEncoding</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="n">ascii</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="n">hPutStr</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="s">"ab</span><span class="se">\</span><span class="err">uDC</span><span class="se">81</span><span class="s">"</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="n">hClose</span><span class="w"> </span><span class="n">h</span>
<span class="o">>>></span><span class="w"> </span><span class="n">openFile</span><span class="w"> </span><span class="s">"sample.txt"</span><span class="w"> </span><span class="kt">ReadWriteMode</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="nf">\</span><span class="n">h</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">hSetEncoding</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="n">ascii</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="n">hGetLine</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="nf">\</span><span class="n">s</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="n">hClose</span><span class="w"> </span><span class="n">h</span>
<span class="s">"ab</span><span class="se">\56449</span><span class="s">"</span>
</pre></div></td></tr></table></div>
<p>なお,この時実行したディレクトリに,以下の内容の <tt class="docutils literal">sample.txt</tt> というファイルが生成される:</p>
<pre class="literal-block">
$ od -tcx1 sample.txt
0000000 a b 201
61 62 81
0000003
</pre>
<p>また,<tt class="docutils literal">56449</tt> の 16 進数表記は <tt class="docutils literal">0xDC81</tt> になる.個人的には,誰が使うのか分からない邪悪なモードという感は強いが,Unicode のサロゲートコードポイントに文字を割り当てないという決定は,こういうところにも影響を及ぼしているということだ.</p>
</div>
<div class="section" id="auto-id-10">
<h2>まとめ<a class="headerlink" href="#auto-id-10" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,今回は Unicode のサロゲートコードポイントができた経緯と,内容の紹介,そして付随する <a class="reference external" href="https://www.python.org/dev/peps/pep-0383/">PEP 383</a> という仕様を紹介した.この辺の理解,ちょっと曖昧だったので,まあいい勉強にはなった.文字コード界隈は,歴史的経緯と実装が合わさって魔窟っすね.</p>
<p>後,GHC の <tt class="docutils literal">Char</tt> の内部管理が,実は素直な Unicode コードポイントではないということは知っていたんだが,その詳細は知らなかったので,理解は進んだ.この辺,資料ほぼ皆無なので,誰も使っていないんだろな.ってことで,今回は以上.</p>
<table class="docutils footnote" frame="void" id="unicode-88" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><a class="reference external" href="https://unicode.org/history/unicode88.pdf">https://unicode.org/history/unicode88.pdf</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="unicode-1-0" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[2]</a></td><td><a class="reference external" href="https://www.unicode.org/versions/Unicode1.0.0/">https://www.unicode.org/versions/Unicode1.0.0/</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="unicode-4-0" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[3]</a></td><td><a class="reference external" href="https://www.unicode.org/versions/Unicode4.0.1/">https://www.unicode.org/versions/Unicode4.0.1/</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="utf-16-endian-variation" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[4]</a></td><td>正確には UTF-16 には2つのバリエーションがあり,コードユニットが2つになった時,ビッグエンディアンで並べるか (UTF-16BE),リトルエンディアンで並べるか (UTF-16LE) が分かれている.通常の UTF-16 は BOM によりこの2つの方式のいずれかを指定することができ,指定されていない場合はビッグエンディアンになる.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="ghc-haskell" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[5]</a></td><td>Haskell の方は,厳密には Haskell の仕様ではなく,Haskell の処理系 GHC の実装仕様である</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="utf-16-surrogateescape" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[6]</a></td><td>ところで,実はこの処理の流れだと UTF-16 とかも対応できる.UTF-16 で正しくデコードできないのは,high surrogate から続けて並んだりといったケースだが,そのような場合デコードできないバイト列は <tt class="docutils literal">0x80</tt> 以上のバイトだからだ.実際,CPython 3.7.8 で確認したところ <tt class="docutils literal">surrogateescape</tt> はエラーなしに動くようだ.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="pep383-security-risk" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-9">[7]</a></td><td>もしこの条件分岐がなかった場合,ASCII の範囲の任意の文字をサロゲートコードポイントとして内部に持ち,ASCII 互換の文字コードでエンコード時に,ちゃんとエンコードしてしまうことになる.そうすると,例えば入力でわざとデコードに失敗する文字コードを選択し,それを ASCII 互換の文字コードにエンコードさせることで,制御文字などをバリデーションを避けて埋め込める可能性がある.これを避ければある程度セキュリティリスクは抑えられるだろうという判断のようだ.また,世の中の多くの文字コード,特にロケール文字コードと呼ばれるものは ASCII 互換である.なので,基本的に ASCII の範囲でデコードが失敗することは少ない.なので,実用上も問題ないということらしい.以上のことは,<a class="reference external" href="https://www.python.org/dev/peps/pep-0383/">PEP 383</a> の Discussion に書かれている.ASCII 以外の範囲で制御文字を持つ何かがあれば結構危うい気がするが,詳しくは調べてない.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/11/unicode-surrogate-codepoint.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/11/unicode-surrogate-codepoint.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>ハイティング代数の性質2020-10-04T14:11:38+09:002020-10-04T14:11:38+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-10-04:/blog/posts/2020/10/heyting-algebra-properties/<p>古典論理の意味論がブール代数によって議論できるように,直観主義論理の意味論はハイティング代数によって考 …</p><p>古典論理の意味論がブール代数によって議論できるように,直観主義論理の意味論はハイティング代数によって考えることができる.ハイティング代数とは,冪で閉じている有界束であり,ブール代数もハイティング代数になる.</p>
<p>というわけで結構題材になるハイティング代数だが,巷でハイティング代数に関しての資料が少なかったりするので,自分のために諸々備忘録を残しておく.</p>
<div class="section" id="auto-id-2">
<h2>ハイティング代数の定義<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まずは基本的なところから。最初に poset を導入する。</p>
<dl class="docutils">
<dt>定義. 半順序 (partial order, poset)</dt>
<dd><p class="first">集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> とそれ上の二項関係 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mo>⊑</mo><mo stretchy="false">)</mo><mo>⊆</mo><mi>A</mi><mo>×</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">(\sqsubseteq) \subseteq A \times A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> の組 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>A</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(A, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> で以下を満たすものを、半順序と呼ぶ:</p>
<dl class="last docutils">
<dt>反射律 (reflexivity)</dt>
<dd>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">x \in A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊑</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \sqsubseteq x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></dd>
<dt>推移律 (transitivity)</dt>
<dd>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">x, y, z \in A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊑</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \sqsubseteq y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> かつ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>⊑</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">y \sqsubseteq z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span> ならば、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊑</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">x \sqsubseteq z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span></dd>
<dt>反対称律 (anti-symmetric)</dt>
<dd>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">x, y \in A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊑</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \sqsubseteq y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> かつ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>⊑</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">y \sqsubseteq x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> ならば、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x = y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></dd>
</dl>
</dd>
</dl>
<p>束の定義方法は色々あるが、今回は poset ベースの束の定義を導入する。</p>
<dl class="docutils">
<dt>定義. 束 (lattice)</dt>
<dd><p class="first">半順序 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>A</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(A, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> で以下を満たすものを、束と呼ぶ:</p>
<ul class="last simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">x, y \in A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> について、上限 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mi>y</mi><mo>∈</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">x \lor y \in A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> が存在する。この時、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \lor y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> を結び (join) と呼ぶ</li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">x, y \in A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> について、下限 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>∈</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">x \land y \in A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> が存在する。この時、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \land y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> を交わり (meet) と呼ぶ</li>
</ul>
</dd>
</dl>
<p>束は、幾つかの代数的性質が成り立つ。</p>
<dl class="docutils">
<dt>定理. 束の性質</dt>
<dd><p class="first">束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について、以下が成り立つ:</p>
<dl class="docutils">
<dt>交換律 (commutative)</dt>
<dd>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>=</mo><mi>y</mi><mo>∧</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \land y = y \land x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span>、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mi>y</mi><mo>=</mo><mi>y</mi><mo>∨</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \lor y = y \lor x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></dd>
<dt>結合律 (associative)</dt>
<dd>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y, z \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">x \land (y \land z) = (x \land y) \land z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span>、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">x \lor (y \lor z) = (x \lor y) \lor z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span></dd>
<dt>吸収律 (absorption)</dt>
<dd>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \land (x \lor y) = x \lor (x \land y) = x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></dd>
<dt>冪等律 (idempotent)</dt>
<dd>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>x</mi><mo>=</mo><mi>x</mi><mo>∨</mo><mi>x</mi><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \land x = x \lor x = x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></dd>
</dl>
<p>証明:</p>
<p class="last">交換律,結合律,冪等律はいいと思うので,吸収律だけ示しておく.といっても,こいつもほぼ自明で,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≤</mo><mi>x</mi><mo>∨</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \leq x \lor y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \land y \leq x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> より,下限,上限の定義から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \land (x \lor y) = x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \lor (x \land y) = x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span>.</p>
</dd>
</dl>
<p>束の中で、空集合に対する上限、下限が存在するもの、つまり最大元、最小元が存在するものを有界束と呼ぶ。</p>
<dl class="docutils">
<dt>定義. 有界束 (bounded lattice)</dt>
<dd><p class="first">束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> で以下を満たすものを,有界束と呼ぶ:</p>
<ul class="last simple">
<li>ある <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊤</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">\top \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">⊤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> が存在し、任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≤</mo><mi mathvariant="normal">⊤</mi></mrow><annotation encoding="application/x-tex">x \leq \top</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊤</span></span></span></span></span> を満たす</li>
<li>ある <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">\bot \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> が存在し、任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi><mo>≤</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">\bot \leq x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> を満たす</li>
</ul>
</dd>
</dl>
<p>ハイティング代数は、有界束の中で冪対象を持つものである。</p>
<dl class="docutils">
<dt>定義. ハイティング代数 (heyting algebra)</dt>
<dd><p class="first">有界束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> で以下を満たすものを、ハイティング代数と呼ぶ:</p>
<ul class="last simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><mi>z</mi><mo>∈</mo><mi>L</mi><mo>∣</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo>≤</mo><mi>y</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\{z \in L \mid x \land z \leq y\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">}</span></span></span></span></span> の上限 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>→</mo><mi>y</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x \to y \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> が存在する。この時、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>→</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \to y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> を冪 (exponential) または相対擬補元 (relative pseudo-complement) と呼ぶ</li>
</ul>
</dd>
</dl>
<p>証明は省略するが,冪の例は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>→</mo><mi>x</mi><mo>=</mo><mi mathvariant="normal">⊤</mi></mrow><annotation encoding="application/x-tex">x \to x = \top</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊤</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊤</mi><mo>→</mo><mi>x</mi><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">\top \to x = x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi><mo>→</mo><mi>x</mi><mo>=</mo><mi mathvariant="normal">⊤</mi></mrow><annotation encoding="application/x-tex">\bot \to x = \top</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊤</span></span></span></span></span> などがある.</p>
</div>
<div class="section" id="auto-id-3">
<h2>ハイティング代数の性質<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>分配律を満たす束を分配束という.</p>
<dl class="docutils">
<dt>定義. 分配束 (distributive lattice)</dt>
<dd><p class="first">束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について、以下を満たすものを分配束と呼ぶ:</p>
<ul class="last simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y, z \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land (y \lor z) = (x \land y) \lor (x \land z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y, z \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \lor (y \land z) = (x \lor y) \land (x \lor z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
</dd>
</dl>
<p>なお,片方のみ成り立てば分配束になる.</p>
<dl class="docutils">
<dt>定理. 分配束の条件</dt>
<dd><p class="first">束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について、以下は同値.</p>
<ol class="arabic simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> は分配束</li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y, z \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land (y \lor z) = (x \land y) \lor (x \land z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y, z \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \lor (y \land z) = (x \lor y) \land (x \lor z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
</ol>
<p>証明:</p>
<p>1 ならば 2,1 ならば 3 は自明.2 ならば 1 は,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi>x</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
(x \lor y) \land (x \lor z)
= ((x \lor y) \land x) \lor ((x \lor y) \land z)
= x \lor (x \land z) \lor (y \land z)
= x \lor (y \land z)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">((</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">((</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></div>
<p class="last">より,示せる.3 ならば 1 も対称的に証明できる.</p>
</dd>
</dl>
<p>ハイティング代数は、分配束になる.</p>
<dl class="docutils">
<dt>定理. ハイティング代数の分配律</dt>
<dd><p class="first">ハイティング代数は,分配束である.</p>
<p>証明:</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land y \leq x \land (y \lor z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>z</mi><mo>≤</mo><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land z \leq x \land (y \lor z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land (y \lor z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \land y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">x \land z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span> の上界になる.よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>≤</mo><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(x \land y) \lor (x \land z) \leq x \land (y \lor z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span>.また,</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land y \leq (x \land y) \lor (x \land z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>z</mi><mo>≤</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land z \leq (x \land y) \lor (x \land z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>より,</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>≤</mo><mo stretchy="false">(</mo><mi>x</mi><mo>→</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">y \leq (x \to (x \land y) \lor (x \land z))</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">))</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>z</mi><mo>≤</mo><mo stretchy="false">(</mo><mi>x</mi><mo>→</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">z \leq (x \to (x \land y) \lor (x \land z))</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">))</span></span></span></span></span></li>
</ul>
<p>よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>→</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \to (x \land y) \lor (x \land z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi></mrow><annotation encoding="application/x-tex">y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>z</mi></mrow><annotation encoding="application/x-tex">z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span> の上界より <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>∨</mo><mi>z</mi><mo>≤</mo><mo stretchy="false">(</mo><mi>x</mi><mo>→</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">y \lor z \leq (x \to (x \land y) \lor (x \land z))</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">))</span></span></span></span></span>.ここから,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo><mo>≤</mo><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>→</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>≤</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
x \land (y \lor z) \leq x \land (x \to (x \land y) \lor (x \land z)) \leq (x \land y) \lor (x \land z)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></div>
<p class="last">よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land (y \lor z) = (x \land y) \lor (x \land z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span> より,分配束になる.</p>
</dd>
</dl>
<p>ついでにだが、通常の有界束は分配律が成り立つとは限らない。反例は以下のもの:</p>
<img alt=":math:`\bot < x, y, z < \top`" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2020/10/heyting-algebra-properties/heyting-algebra-properties/not-distributive-lattice.png"/>
<p>この時、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi><mo mathvariant="normal">≠</mo><mi mathvariant="normal">⊤</mi><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \lor (y \land z) = x \neq \top = (x \lor y) \land (x \lor z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span> になる。さて,束の元には補元が存在する場合がある.</p>
<dl class="docutils">
<dt>定義. 補 (complement)</dt>
<dd><p class="first">有界束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> の元 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について,</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">x \land y \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊤</mi><mo>≤</mo><mi>x</mi><mo>∨</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">\top \leq x \lor y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord">⊤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></li>
</ul>
<p class="last">を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">y \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> の補と呼ぶ</p>
</dd>
</dl>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊤</mi></mrow><annotation encoding="application/x-tex">\top</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊤</span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> は互いに補の関係になる.なお,有界束において一般に補は一意とは限らない.例えば,上の分配律が成り立たない束において,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> の補は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi></mrow><annotation encoding="application/x-tex">y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>z</mi></mrow><annotation encoding="application/x-tex">z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span> 両方になる.もちろん存在するとも限らない.これは,線形な束を思い描いてみるといいだろう.ところで,分配束において補は存在するなら一意に定まる.</p>
<dl class="docutils">
<dt>定理. 分配束における補の一意性</dt>
<dd><p class="first">有界な分配束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について,</p>
<ul class="simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y, z \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \land (y \lor z) = (x \land y) \lor (x \land z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x, y, z \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x \lor (y \land z) = (x \lor y) \land (x \lor z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>が成り立つ時,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> についてその補は高々1つである</p>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> の補 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mn>1</mn></msub><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">y_1 \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mn>2</mn></msub><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">y_2 \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> が存在する時,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mn>1</mn></msub><mo>=</mo><msub><mi>y</mi><mn>1</mn></msub><mo>∧</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>2</mn></msub><mo>∨</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>1</mn></msub><mo>∧</mo><msub><mi>y</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>1</mn></msub><mo>∧</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>1</mn></msub><mo>∧</mo><msub><mi>y</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>2</mn></msub><mo>∧</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>y</mi><mn>2</mn></msub><mo>∧</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>1</mn></msub><mo>∨</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>y</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">
y_1 = y_1 \land (y_2 \lor x) = (y_1 \land y_2) \lor (y_1 \land x) = (y_1 \land y_2) \lor (y_2 \land x) = y_2 \land (y_1 \lor x) = y_2
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></div>
<p class="last">より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mn>1</mn></msub><mo>=</mo><msub><mi>y</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">y_1 = y_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span>.よって,存在すれば補は一意.</p>
</dd>
</dl>
<p>ハイティング代数において補は存在するとは限らないが,ハイティング代数は分配束より存在すれば一意である.さらに,ハイティング代数においては補が存在すればその形を特定できる.</p>
<dl class="docutils">
<dt>定義. 擬似補 (pseudo-complement)</dt>
<dd>ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>H</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(H, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について、その要素 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> に対し、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>→</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">x \to \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> を擬似補と言い、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span> と表記する</dd>
</dl>
<p>ハイティング代数において,補が存在すればそれは <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span> と一致する.</p>
<dl class="docutils">
<dt>定理. 擬似補と補の一意性</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>H</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(H, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> の元 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について,その補が存在する時,それは <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span> のみである</p>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> の補 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">y \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> が存在する時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">x \land y \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> より <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">y \leq \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span> である.この時,</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">x \land \neg x \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊤</mi><mo>≤</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo>≤</mo><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\top \leq x \lor y \leq x \lor \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord">⊤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span></li>
</ul>
<p class="last">より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span> は補である.さらに,ハイティング代数は分配束なので,補は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span> のみである.</p>
</dd>
</dl>
<p>ハイティング代数ではド・モルガン則は片方のみ成り立つ.</p>
<dl class="docutils">
<dt>定理. ド・モルガン則 (De Morgan's law)</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>H</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(H, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について、以下が成り立つ:</p>
<ul class="simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x, y \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\neg x \land \neg y = \neg (x \lor y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>証明:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">⊥</mi><mo>∨</mo><mi mathvariant="normal">⊥</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">
(x \lor y) \land \neg x \land \neg y
= (x \land \neg x \land \neg y) \lor (y \land \neg \land \neg y)
= \bot \lor \bot
\leq \bot
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span></div>
<p>より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\neg x \land \neg y \leq \neg (x \lor y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span>.また,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>≤</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>y</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">
x \land \neg (x \lor y)
\leq (x \land \neg (x \lor y)) \lor (y \land \neg (x \lor y))
= (x \lor y) \land \neg (x \lor y)
\leq \bot
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span></div>
<p class="last">より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg (x \lor y) \leq \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span>.対称性より <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">¬</mi><mi>y</mi></mrow><annotation encoding="application/x-tex">\neg (x \lor y) \leq \neg y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span>.よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi></mrow><annotation encoding="application/x-tex">\neg (x \lor y) \leq \neg x \land \neg y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\neg x \land \neg y = \neg (x \lor y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span>.</p>
</dd>
</dl>
</div>
<div class="section" id="auto-id-4">
<h2>ブール代数と二重否定変換<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ハイティング代数のインスタンスにブール代数がある.</p>
<dl class="docutils">
<dt>定義. ブール代数 (boolean algebra)</dt>
<dd><p class="first">分配束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>L</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(L, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> で以下を満たすものを、ブール代数と呼ぶ:</p>
<ul class="last simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>L</mi></mrow><annotation encoding="application/x-tex">x \in L</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span> について、その補が存在する</li>
</ul>
</dd>
<dt>定理. ブール代数はハイティング代数</dt>
<dd><p class="first">ブール代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>B</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(B, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> は,ハイティング代数である</p>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">x, y \in B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> の補を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> とする.この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>→</mo><mi>y</mi><mo>=</mo><mi>a</mi><mo>∨</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \to y = a \lor y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> を示す.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>a</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>a</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">
x \land (a \lor y) = (x \land a) \lor (x \land y) = x \land y \leq y
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></div>
<p>であり,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>z</mi><mo>≤</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \land z \leq y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> となる <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>z</mi><mo>∈</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">z \in B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> について,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>z</mi><mo>=</mo><mi>z</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>a</mi><mo>∨</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>z</mi><mo>∧</mo><mi>a</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>z</mi><mo stretchy="false">)</mo><mo>≤</mo><mi>a</mi><mo>∨</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">
z = z \land (a \lor x) = (z \land a) \lor (x \land z) \leq a \lor y
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></div>
<p class="last">より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>∨</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">a \lor y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>→</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \to y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> の条件を満たす.よって,任意の元について冪が存在するため,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>B</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(B, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> はハイティング代数.</p>
</dd>
</dl>
<p>ハイティング代数がブール代数になる条件として,以下が知られている.</p>
<dl class="docutils">
<dt>定理. ブール代数の同値条件</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>H</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(H, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について,以下は同値</p>
<ol class="arabic simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> はブール代数</li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>=</mo><mi mathvariant="normal">⊤</mi></mrow><annotation encoding="application/x-tex">x \lor \neg x = \top</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊤</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg \neg x = x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></li>
</ol>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">x \land \neg x \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> であること,ブール代数がハイティング代数であることから,1 と 2 の同値性はいいと思う.</p>
<p>2 から 3 は,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi>x</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">
\neg \neg x = \neg \neg x \land (x \lor \neg x)
= (\neg \neg x \land x) \lor (\neg \neg x \land \neg x)
= \neg \neg x \land x
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>=</mo><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi>x</mi><mo stretchy="false">)</mo><mo>∨</mo><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>∧</mo><mi>x</mi><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">
= (\neg \neg x \land x) \lor (x \land \neg x)
= (\neg \neg x \lor \neg x) \land x = x
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></div>
<p>より示せる.3 から 2 は,ハイティング代数で適用できるド・モルガン則を使用して,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">⊥</mi><mo>=</mo><mi mathvariant="normal">⊤</mi></mrow><annotation encoding="application/x-tex">
x \lor \neg x = \neg \neg (x \lor \neg x) = \neg (\neg x \land \neg \neg x) = \neg \bot = \top
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">¬⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊤</span></span></span></span></span></div>
<p class="last">より示せる.</p>
</dd>
</dl>
<p>ブール代数では,2つめのド・モルガン則も示せる.</p>
<dl class="docutils">
<dt>定理. ド・モルガン則 (De Morgan's law)</dt>
<dd><p class="first">ブール代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>B</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(B, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について、以下が成り立つ:</p>
<ul class="simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x, y \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\neg x \lor \neg y = \neg (x \land y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>証明:</p>
<p>ブール代数では二重否定の除去ができることから,ハイティング代数上で成り立つド・モルガン則を使用して,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∨</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\neg x \lor \neg y
= \neg \neg (\neg x \lor \neg y)
= \neg (\neg \neg x \land \neg \neg y)
= \neg (x \land y)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></div>
<p class="last">のように示せる.</p>
</dd>
</dl>
<p>さて,ハイティング代数からブール代数への変換方法として,二重否定変換というものが知られている.これは,名前の通り全ての元に二重否定をかますような変換だ.それを示すため,まず準備として補題を用意する.</p>
<dl class="docutils">
<dt>補題.</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>H</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(H, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について,以下が成り立つ:</p>
<ul class="simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">x \leq \neg \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x, y \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≤</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \leq y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> ならば <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg y \leq \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span></li>
</ul>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi>x</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\neg x \land x \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">x \leq \neg \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span></span></span></span></span>.また,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≤</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \leq y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> の時,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi>y</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">
x \land \neg y \leq y \land \neg y \leq \bot
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span></div>
<p class="last">より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg y \leq \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span>.</p>
</dd>
<dt>補題.</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>H</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(H, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について,以下が成り立つ:</p>
<ul class="simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg \neg \neg x = \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">x, y \in H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi></mrow><annotation encoding="application/x-tex">\neg \neg (x \land y) = \neg \neg x \land \neg \neg y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></li>
</ul>
<p>証明:</p>
<p>前の補題から,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg x \leq \neg \neg \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬¬</span><span class="mord mathnormal">x</span></span></span></span></span>.また,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>x</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg x \leq \neg \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg \neg \neg x \leq \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord">¬¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span>.よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg \neg \neg x = \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></span>.</p>
<p>また,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x \land y \leq x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \land y \leq y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> から,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg \neg (x \land y) \leq \neg \neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi></mrow><annotation encoding="application/x-tex">\neg \neg (x \land y) \leq \neg \neg y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi></mrow><annotation encoding="application/x-tex">\neg \neg (x \land y) \leq \neg \neg x \land \neg \neg y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span>.さて,後 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\neg \neg x \land \neg \neg y \leq \neg \neg (x \land y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span> を示せれば良い.これを示すには,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\neg (x \land y) \land \neg \neg x \land \neg \neg y \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> を示せれば良い.</p>
<p>ところで,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\neg (x \land y) \land x \land y \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> より,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi>x</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi>y</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi></mrow><annotation encoding="application/x-tex">
\neg (x \land y) \land x \leq \neg y = \neg \neg \neg y
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></div>
<p class="last">であるため,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\neg (x \land y) \land x \land \neg \neg y \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> である.同様に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> についても同じ操作から,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi><mo>≤</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\neg (x \land y) \land \neg \neg x \land \neg \neg y \leq \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> となる.よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∧</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>y</mi></mrow><annotation encoding="application/x-tex">\neg \neg (x \land y) = \neg \neg x \land \neg \neg y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span>.</p>
</dd>
</dl>
<p>これより,二重否定変換はハイティング代数上の準同型になり,二重否定の除去を付加できる.これにより,ハイティング代数からブール代数を生成できる.</p>
<dl class="docutils">
<dt>定理. 二重否定変換 (double-negation translation)</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>H</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(H, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>H</mi><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi></mrow></msub><mo>=</mo><mo stretchy="false">(</mo><mo stretchy="false">{</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo>∣</mo><mi>x</mi><mo>∈</mo><mi>H</mi><mo stretchy="false">}</mo><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">H_{\neg\neg} = (\{\neg \neg x \mid x \in H\}, \sqsubseteq)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">¬¬</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">({</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">)</span></span></span></span></span> はブール代数である</p>
<p>証明:</p>
<p class="last">前の補題から,元の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∧</mo></mrow><annotation encoding="application/x-tex">\land</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">∧</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>H</mi><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi></mrow></msub></mrow><annotation encoding="application/x-tex">H_{\neg\neg}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">¬¬</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> でも閉じている.また,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">x \leq \neg\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span></span></span></span></span> より,冪も保存される.よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>H</mi><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi></mrow></msub></mrow><annotation encoding="application/x-tex">H_{\neg\neg}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">¬¬</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> はハイティング代数.さらに,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg\neg(\neg\neg x) = \neg\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span></span></span></span></span> であり,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>H</mi><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi></mrow></msub></mrow><annotation encoding="application/x-tex">H_{\neg\neg}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">¬¬</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> はブール代数になる.</p>
</dd>
</dl>
</div>
<div class="section" id="auto-id-5">
<h2>圏論的視点<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今までは通常の束論の議論でハイティング代数を取り扱ってきたが,圏論的な議論もしておく.まず,半順序での最大下界,最小上界は,poset での直積,直和になる.これは,定義を比べてみれば分かると思う.そして,最小元,最大元は始対象,終対象に相当する.よって,有界束とは,finitely complete かつ cocomplete な poset のことになる <a class="footnote-reference" href="#notice-finitely-complete" id="auto-id-6">[1]</a> .</p>
<dl class="docutils">
<dt>定義. 有界束</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> が有界束とは,以下を満たすこと</p>
<ul class="last simple">
<li>有限積を持つ (finitely complete)</li>
<li>有限余積を持つ (finitely cocomplete)</li>
</ul>
</dd>
</dl>
<p>ハイティング代数は,有界束のなかで CCC (Cartesian Closed Category) になるものである.すなわち,冪も持つような poset になる.</p>
<dl class="docutils">
<dt>定義. ハイティング代数</dt>
<dd><p class="first">有界束 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> がハイティング代数とは,以下を満たすこと</p>
<ul class="last simple">
<li>CCC である</li>
</ul>
</dd>
</dl>
<p>冪の定義も照らし合わせてみるとそのままだが,一応確認しておくと,</p>
<img alt=":math:`C(X \times Y, Z) \simeq C(X, Z^Y)`" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2020/10/heyting-algebra-properties/heyting-algebra-properties/exponential-object.png"/>
<p>が冪対象の定義で,この時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>z</mi><mi>y</mi></msup><mo>∧</mo><mi>y</mi><mo>=</mo><msup><mi>z</mi><mi>y</mi></msup><mo>×</mo><mi>y</mi><mo>≤</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">z^y \land y = z^y \times y \leq z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7477em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span> かつ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>×</mo><mi>y</mi><mo>=</mo><mi>x</mi><mo>∧</mo><mi>y</mi><mo>≤</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">x \times y = x \land y \leq z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span> となる <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> について <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≤</mo><msup><mi>z</mi><mi>y</mi></msup></mrow><annotation encoding="application/x-tex">x \leq z^y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span></span></span></span></span></span></span></span> となる.冪の随伴関係 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo stretchy="false">(</mo><mi>X</mi><mo>×</mo><mi>Y</mi><mo separator="true">,</mo><mi>Z</mi><mo stretchy="false">)</mo><mo>≃</mo><mi>C</mi><mo stretchy="false">(</mo><mi>X</mi><mo separator="true">,</mo><msup><mi>Z</mi><mi>Y</mi></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">C(X \times Y, Z) \simeq C(X, Z^Y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0913em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">Y</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> がそのままで,つまりハイティング代数とは,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mo>∧</mo><mi>Y</mi></mrow><annotation encoding="application/x-tex">- \land Y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span></span></span></span></span> が右随伴を持つような有界束のことになる.ついでに,CCC で finite coproduct を持つような圏を BCCC (BiCartesian Closed Category) と言うらしい.ハイティング代数は,この言葉を使うと poset で BCCC になるものと言える.</p>
<p>さて,左随伴の有用な性質として,余極限を保存すると言うものがある.つまり,ハイティング代数では <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo>−</mo></mrow><annotation encoding="application/x-tex">x \land -</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span></span></span></span></span> は余極限を保存する.ここから直ちに分配束であることが導ける.</p>
<dl class="docutils">
<dt>定理.</dt>
<dd><p class="first">ハイティング代数は,分配束である.</p>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><mo>−</mo></mrow><annotation encoding="application/x-tex">x \land -</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">−</span></span></span></span></span> は余極限を保存するため,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∧</mo><munder><mo>⋁</mo><mi>y</mi></munder><mi>y</mi><mo>=</mo><munder><mo>⋁</mo><mi>y</mi></munder><mi>x</mi><mo>∧</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">
x \land \bigvee_y y = \bigvee_y x \land y
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.4361em;vertical-align:-1.3861em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.9em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⋁</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.3861em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4361em;vertical-align:-1.3861em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.9em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⋁</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.3861em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></div>
<p class="last">である.</p>
</dd>
</dl>
<p>ところで,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span></span></span></span></span> はハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> 上の反変関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>:</mo><mi>H</mi><mo>→</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup></mrow><annotation encoding="application/x-tex">\neg: H \to H^{\mathrm{op}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span></span></span></span></span> になる.逆にも <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>:</mo><msup><mi>H</mi><mo lspace="0em" rspace="0em"><mi>o</mi><mi>p</mi></mo></msup><mo>→</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">\neg: H^{\mathop{op}} \to H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mop mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> を張れて,こいつらは随伴になる.一般に,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> の対象 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi></mrow><annotation encoding="application/x-tex">X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>X</mi><mo>−</mo></msup><mo>:</mo><mi>H</mi><mo>→</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup></mrow><annotation encoding="application/x-tex">X^-: H \to H^{\mathrm{op}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7713em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span></span></span></span></span> は左随伴になる.</p>
<dl class="docutils">
<dt>定理.</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>H</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">X \in |H|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord">∣</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>X</mi><mo>−</mo></msup><mo>:</mo><mi>H</mi><mo>→</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup></mrow><annotation encoding="application/x-tex">X^-: H \to H^{\mathrm{op}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7713em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span></span></span></span></span> は右随伴を持つ.</p>
<p>証明:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup><mo stretchy="false">(</mo><msup><mi>X</mi><mi>Y</mi></msup><mo separator="true">,</mo><mi>Z</mi><mo stretchy="false">)</mo><mo>≃</mo><mi>H</mi><mo stretchy="false">(</mo><mi>Z</mi><mo separator="true">,</mo><msup><mi>X</mi><mi>Y</mi></msup><mo stretchy="false">)</mo><mo>≃</mo><mi>H</mi><mo stretchy="false">(</mo><mi>Y</mi><mo>×</mo><mi>Z</mi><mo separator="true">,</mo><mi>X</mi><mo stretchy="false">)</mo><mo>≃</mo><mi>H</mi><mo stretchy="false">(</mo><mi>Y</mi><mo separator="true">,</mo><msup><mi>X</mi><mi>Z</mi></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
H^{\mathrm{op}}(X^Y, Z)
\simeq H(Z, X^Y)
\simeq H(Y \times Z, X)
\simeq H(Y, X^Z)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1413em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">Y</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1413em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">Y</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1413em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">Z</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p class="last">より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>X</mi><mo>−</mo></msup><mo>:</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup><mo>→</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">X^-: H^{\mathrm{op}} \to H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7713em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> が右随伴になり,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>X</mi><mo>−</mo></msup><mo>⊣</mo><msup><mi>X</mi><mo>−</mo></msup><mo>:</mo><mi>H</mi><mo>→</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup></mrow><annotation encoding="application/x-tex">X^- \dashv X^-: H \to H^{\mathrm{op}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7713em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7713em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span></span></span></span></span> になる.</p>
</dd>
</dl>
<p>ところで,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>:</mo><mi>H</mi><mo>→</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup></mrow><annotation encoding="application/x-tex">\neg: H \to H^{\mathrm{op}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span></span></span></span></span> が左随伴を持つ場合がある.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>:</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup><mo>→</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">\neg: H^{\mathrm{op}} \to H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> がその左随伴になる <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> がブール代数である.</p>
<dl class="docutils">
<dt>定義. ブール代数</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> がブール代数とは,以下を満たすこと:</p>
<ul class="last simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>⊣</mo><mi mathvariant="normal">¬</mi><mo>:</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup><mo>→</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">\neg \dashv \neg: H^{\mathrm{op}} \to H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span></li>
</ul>
</dd>
</dl>
<p>この定義がブール代数の条件に合うことを確認する前に少々寄り道する.さて,随伴同値 (adjoint equivalence) と言う条件がある.これは,随伴による単子 (unit),余単子 (counit) が自然同型になることである.</p>
<dl class="docutils">
<dt>定義. 随伴同値</dt>
<dd>随伴 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>⊣</mo><mi>G</mi></mrow><annotation encoding="application/x-tex">F \dashv G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span> について,その単子,余単子が自然同型である時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>⊣</mo><mi>G</mi></mrow><annotation encoding="application/x-tex">F \dashv G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span> を随伴同値という.</dd>
</dl>
<p>随伴同値の場合,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>⊣</mo><mi>G</mi></mrow><annotation encoding="application/x-tex">F \dashv G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span> かつ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>⊣</mo><mi>F</mi></mrow><annotation encoding="application/x-tex">G \dashv F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> になる.</p>
<dl class="docutils">
<dt>定理.</dt>
<dd><p class="first">随伴 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>⊣</mo><mi>G</mi></mrow><annotation encoding="application/x-tex">F \dashv G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span> が随伴同値ならば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>⊣</mo><mi>F</mi></mrow><annotation encoding="application/x-tex">G \dashv F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> である</p>
<p>証明:</p>
<p>unit <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>η</mi><mo>:</mo><mn>1</mn><mo>⇒</mo><mi>G</mi><mo>∘</mo><mi>F</mi></mrow><annotation encoding="application/x-tex">\eta: 1 \Rightarrow G \circ F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>,counit <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi><mo>:</mo><mi>F</mi><mo>∘</mo><mi>G</mi><mo>⇒</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\epsilon: F \circ G \Rightarrow 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> が自然同型である時,それぞれの逆射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>ϵ</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo>:</mo><mn>1</mn><mo>⇒</mo><mi>F</mi><mo>∘</mo><mi>G</mi></mrow><annotation encoding="application/x-tex">\epsilon^{-1}: 1 \Rightarrow F \circ G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>t</mi><msup><mi>a</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo>:</mo><mi>G</mi><mo>∘</mo><mi>F</mi><mo>⇒</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">eta^{-1}: G \circ F \Rightarrow 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord mathnormal">e</span><span class="mord mathnormal">t</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> が存在する.この時,</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi>G</mi><msup><mi>ϵ</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup></mrow></mpadded></mover><mi>G</mi><mi>F</mi><mi>G</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>η</mi><mi>G</mi><mrow><mo>−</mo><mn>1</mn></mrow></msubsup></mpadded></mover><mi>G</mi></mrow><annotation encoding="application/x-tex">G \xrightarrow{G \epsilon^{-1}} GFG \xrightarrow{\eta^{-1}_G} G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">G</span><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal">GFG</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.1874em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">G</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3126em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>ϵ</mi><mi>F</mi><mrow><mo>−</mo><mn>1</mn></mrow></msubsup></mpadded></mover><mi>F</mi><mi>G</mi><mi>F</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi>F</mi><msup><mi>η</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup></mrow></mpadded></mover><mi>F</mi></mrow><annotation encoding="application/x-tex">F \xrightarrow{\epsilon^{-1}_F} FGF \xrightarrow{F \eta^{-1}} F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.1874em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3126em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">FGF</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span></li>
</ul>
<p>はそれぞれ</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi>F</mi><mi>η</mi></mrow></mpadded></mover><mi>F</mi><mi>G</mi><mi>F</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msub><mi>ϵ</mi><mi>F</mi></msub></mpadded></mover><mi>F</mi></mrow><annotation encoding="application/x-tex">F \xrightarrow{F \eta} FGF \xrightarrow{\epsilon_F} F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1113em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1003em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">η</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">FGF</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3567em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1433em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msub><mi>η</mi><mi>G</mi></msub></mpadded></mover><mi>G</mi><mi>F</mi><mi>G</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi>G</mi><mi>ϵ</mi></mrow></mpadded></mover><mi>G</mi></mrow><annotation encoding="application/x-tex">G \xrightarrow{\eta_G} GFG \xrightarrow{G \epsilon} G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3567em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">G</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1433em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1113em;vertical-align:-0.011em;"></span><span class="mord mathnormal">GFG</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1003em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">G</span><span class="mord mathnormal mtight">ϵ</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span></li>
</ul>
<p class="last">の逆射になる.よって恒等射になるため,それぞれが unit / counit になる随伴 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>⊣</mo><mi>F</mi></mrow><annotation encoding="application/x-tex">G \dashv F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> が作れる.</p>
</dd>
</dl>
<p>ところで,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>∘</mo><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg \circ \neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span></span></span></span></span> は恒等関手,つまり二重否定の除去が成り立つとすると,この時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>⊣</mo><mi mathvariant="normal">¬</mi><mo>:</mo><mi>H</mi><mo>→</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup></mrow><annotation encoding="application/x-tex">\neg \dashv \neg: H \to H^{\mathrm{op}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span></span></span></span></span> の unit は自然同型になる.また,unit が自然同型になるならば二重否定の除去ができる.つまりブール代数とは,ハイティング代数で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span></span></span></span></span> が随伴同値になるものである <a class="footnote-reference" href="#notice-adjoint-equivalence-and-self-adjoint" id="auto-id-7">[2]</a> .</p>
<dl class="docutils">
<dt>定理. ブール代数の条件</dt>
<dd><p class="first">ハイティング代数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> について,以下は同値</p>
<ol class="arabic simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> はブール代数</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>∘</mo><mi mathvariant="normal">¬</mi><mo>:</mo><mi>H</mi><mo>→</mo><mi>H</mi></mrow><annotation encoding="application/x-tex">\neg \circ \neg: H \to H</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></span> は恒等関手</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>⊣</mo><mi mathvariant="normal">¬</mi><mo>:</mo><mi>H</mi><mo>→</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup></mrow><annotation encoding="application/x-tex">\neg \dashv \neg: H \to H^{\mathrm{op}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span></span></span></span></span> は随伴同値</li>
</ol>
<p>証明:</p>
<p>3 から 1 はよい.1 から 2 は,</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi><mo stretchy="false">(</mo><mi>Y</mi><mo separator="true">,</mo><mi mathvariant="normal">¬</mi><mi>X</mi><mo stretchy="false">)</mo><mo>≃</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi>X</mi><mo separator="true">,</mo><mi>Y</mi><mo stretchy="false">)</mo><mo>≃</mo><mi>H</mi><mo stretchy="false">(</mo><mi>X</mi><mo separator="true">,</mo><mi mathvariant="normal">¬</mi><mi>Y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">H(Y, \neg X) \simeq H^{\mathrm{op}}(\neg X, Y) \simeq H(X, \neg Y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi>X</mi><mo separator="true">,</mo><mi>Y</mi><mo stretchy="false">)</mo><mo>≃</mo><msup><mi>H</mi><mrow><mi mathvariant="normal">o</mi><mi mathvariant="normal">p</mi></mrow></msup><mo stretchy="false">(</mo><mi>X</mi><mo separator="true">,</mo><mi mathvariant="normal">¬</mi><mi>Y</mi><mo stretchy="false">)</mo><mo>≃</mo><mi>H</mi><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi>Y</mi><mo separator="true">,</mo><mi>X</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">H(\neg X, Y) \simeq H^{\mathrm{op}}(X, \neg Y) \simeq H(\neg Y, X)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">op</span></span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi>X</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mn>1</mn></mpadded></mover><mi mathvariant="normal">¬</mi><mi>X</mi></mrow><annotation encoding="application/x-tex">\neg X \xrightarrow{1} \neg X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0841em;vertical-align:-0.011em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0731em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> に対応する射</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>X</mi></mrow><annotation encoding="application/x-tex">X \leq \neg\neg X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>X</mi><mo>≤</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">\neg\neg X \leq X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span></li>
</ul>
<p class="last">が存在する.よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>X</mi><mo>=</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">\neg\neg X = X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> であることより,示せる.2 から 3 は,unit / counit が恒等関手から恒等関手への口頭変換になることから自明.</p>
</dd>
</dl>
<p>ところで,ブール代数に限らずハイティング代数では <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>⊣</mo><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg \dashv \neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span></span></span></span></span> だった.随伴からはモナドが作れるので,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg\neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span></span></span></span></span> はモナドになる.この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg\neg(\neg\neg x) \leq \neg\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span></span></span></span></span> がモナドの自然変換から作れるため,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg\neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span></span></span></span></span> により作られる subcategory がハイティング代数であれば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mo stretchy="false">(</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">\neg\neg(\neg\neg x) = \neg\neg x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬¬</span><span class="mopen">(</span><span class="mord">¬¬</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span><span class="mord mathnormal">x</span></span></span></span></span> になる.つまり,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg\neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span></span></span></span></span> により作られる subcategory はブール代数になる.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg\neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬¬</span></span></span></span></span> により作られる subcategory がハイティング代数であることは,finite product / finite coproduct / implication を保存することを地道に証明する方法しか知らないので割愛する.誰か他の方法知ってたら教えて欲しい <a class="footnote-reference" href="#notice-double-negation" id="auto-id-8">[4]</a>.</p>
</div>
<div class="section" id="auto-id-9">
<h2>まとめ<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>てことで,ハイティング代数は BCCC になる poset で,ブール代数は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>0</mn><mo>−</mo></msup></mrow><annotation encoding="application/x-tex">0^-</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7713em;"></span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span></span></span></span></span></span></span></span></span> が随伴同値になるハイティング代数だよ,何か問題でも?</p>
<p>なお,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>X</mi><mo>−</mo></msup></mrow><annotation encoding="application/x-tex">X^-</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7713em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span></span></span></span></span></span></span></span></span> が左随伴になるって話から,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>x</mi><mo>∨</mo><mi>y</mi><mo stretchy="false">)</mo><mo>⇒</mo><mi>z</mi><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>⇒</mo><mi>z</mi><mo stretchy="false">)</mo><mo>∧</mo><mo stretchy="false">(</mo><mi>y</mi><mo>⇒</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(x \lor y) \Rightarrow z = (x \Rightarrow z) \land (y \Rightarrow z)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span> が直ちに示せたり <a class="footnote-reference" href="#notice-exponential-contravariance" id="auto-id-10">[3]</a>,随伴 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">¬</mi><mo>⊣</mo><mi mathvariant="normal">¬</mi></mrow><annotation encoding="application/x-tex">\neg \dashv \neg</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">¬</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span></span></span></span></span> の同値性 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi><mo stretchy="false">(</mo><mi>Y</mi><mo separator="true">,</mo><mi mathvariant="normal">¬</mi><mi>X</mi><mo stretchy="false">)</mo><mo>≃</mo><mi>H</mi><mo stretchy="false">(</mo><mi>X</mi><mo separator="true">,</mo><mi mathvariant="normal">¬</mi><mi>Y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">H(Y, \neg X) \simeq H(X, \neg Y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span></span> に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mo>=</mo><mi mathvariant="normal">¬</mi><mi>Z</mi></mrow><annotation encoding="application/x-tex">X = \neg Z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Y</mi><mo>=</mo><mi>Z</mi></mrow><annotation encoding="application/x-tex">Y = Z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span></span> すれば <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Z</mi><mo>≤</mo><mi mathvariant="normal">¬</mi><mi mathvariant="normal">¬</mi><mi>Z</mi></mrow><annotation encoding="application/x-tex">Z \leq \neg\neg Z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">¬¬</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span></span></span></span></span> が直ちに示せたりして便利.まあ,その証明が相手に通じるかは置いといて.てことで,今回は以上.</p>
<table class="docutils footnote" frame="void" id="notice-finitely-complete" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[1]</a></td><td>finitely complete になるには厳密には,finite product と equalizer の存在が必要になる.ただ,今回は poset なので,任意の対象間に射はたかだか一つしか存在しないため,equalizer は自明に存在する.finitely cocomplete も同様.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-adjoint-equivalence-and-self-adjoint" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[2]</a></td><td>一般には,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>⊣</mo><mi>G</mi></mrow><annotation encoding="application/x-tex">F \dashv G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>G</mi><mo>⊣</mo><mi>F</mi></mrow><annotation encoding="application/x-tex">G \dashv F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> の時に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>⊣</mo><mi>G</mi></mrow><annotation encoding="application/x-tex">F \dashv G</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span> が随伴同値になるとは限らない.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-exponential-contravariance" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-10">[3]</a></td><td><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>X</mi><mo>−</mo></msup></mrow><annotation encoding="application/x-tex">X^-</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7713em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span></span></span></span></span></span></span></span></span> は反変であることに注意.反変なので,product / coproduct が逆転する.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-double-negation" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-8">[4]</a></td><td>某勉強会でそのうち出てくる?</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/10/heyting-algebra-properties.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/10/heyting-algebra-properties.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Prometheus Operator で k8s を監視する2020-07-26T08:38:44+09:002020-07-26T08:38:44+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-07-26:/blog/posts/2020/07/prometheus-operator/<p>Prometheus は、メトリクスの監視を行うためのモニタリングツールだ。各種メトリクスを出す exporter とそれを集計する Prometheus サーバ、及 …</p><p>Prometheus は、メトリクスの監視を行うためのモニタリングツールだ。各種メトリクスを出す exporter とそれを集計する Prometheus サーバ、及びその集計結果を監視しアラートを出すアラートマネージャで主に構成されている。Prometheus それ自体は便利なんだが、Kubernetes クラスタを監視したい場合色々追加で設定が必要で、結構めんどくさい。そこで、Kubernetes 用に Prometheus をカスタマイズして提供してくれるパッケージがいくつか出ている。今回はそのうちの Prometheus Operator を触る機会があって、せっかくなので使い方を備忘録として残しておく。</p>
<div class="section" id="prometheus-operator">
<h2>Prometheus Operator のインストール<a class="headerlink" href="#prometheus-operator" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まずは、Kubernetes / helm が入った環境用意する。一応、Kubernetes のバックエンドは今回は Docker を想定する。Kubernetes 自体は Windows / macOS なら Docker Desktop で付属としてついてくるのでそれを使うといいだろう。WSL2 の環境なら、</p>
<ol class="arabic simple">
<li>Docker Desktop をインストール</li>
<li>設定から「Kubernetes」->「Enable Kubernetes」</li>
<li>「Resources」->「WSL Integration」-> 普段使ってる WSL コンテナを有効化</li>
</ol>
<p>すれば、WSL コンテナ内で <tt class="docutils literal">docker</tt> / <tt class="docutils literal">kubectl</tt> などの CLI が使えるようになる。Helm は、大体各種パッケージマネージャでインストールできる。Linuxbrew とか使って、</p>
<pre class="literal-block">
brew install helm
</pre>
<p>とかすれば入る。後は、</p>
<pre class="literal-block">
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
</pre>
<p>とかで標準のチャートリポジトリを追加しておく。後、Kubernetes Dashboard もデプロイしておくとよい。こっちも helm で入れられる:</p>
<pre class="literal-block">
helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
kubectl create namespace kubernetes-dashboard
helm install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard \
--namespace kubernetes-dashboard \
--set protocolHttp=true,service.externalPort=80
</pre>
<p>Prometheus Operator はかなり色々入るので名前空間を分けておいた方がいい。今回は <tt class="docutils literal">prometheus</tt> という名前空間を作って、そこにインストールしていく。<tt class="docutils literal">helm</tt> で簡単に入るので、それでインストールする:</p>
<pre class="literal-block">
kubectl create namespace prometheus
helm install prometheus stable/prometheus-operator --namespace prometheus
</pre>
<p>ポッドの様子を見てみる:</p>
<pre class="literal-block">
$ kubectl -n prometheus get pods
NAME READY STATUS RESTARTS AGE
alertmanager-prometheus-prometheus-oper-alertmanager-0 2/2 Running 0 77s
prometheus-grafana-8c6966f8f-m45xx 2/2 Running 0 99s
prometheus-kube-state-metrics-6df5d44568-p464c 1/1 Running 0 99s
prometheus-prometheus-node-exporter-2r7vq 1/1 Running 0 99s
prometheus-prometheus-oper-operator-749cd475f6-j7ftd 2/2 Running 0 99s
prometheus-prometheus-prometheus-oper-prometheus-0 3/3 Running 1 68s
</pre>
<p>サービスも見てみると、</p>
<pre class="literal-block">
$ kubectl -n prometheus get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 2m33s
prometheus-grafana ClusterIP 10.111.67.1 <none> 80/TCP 2m55s
prometheus-kube-state-metrics ClusterIP 10.97.237.255 <none> 8080/TCP 2m55s
prometheus-operated ClusterIP None <none> 9090/TCP 2m24s
prometheus-prometheus-node-exporter ClusterIP 10.100.44.54 <none> 9100/TCP 2m55s
prometheus-prometheus-oper-alertmanager ClusterIP 10.98.127.253 <none> 9093/TCP 2m55s
prometheus-prometheus-oper-operator ClusterIP 10.97.208.129 <none> 8080/TCP,443/TCP 2m55s
prometheus-prometheus-oper-prometheus ClusterIP 10.98.54.131 <none> 9090/TCP 2m55s
</pre>
<p>みたいな感じになる。おおむねそれぞれのサービスは</p>
<dl class="docutils">
<dt><tt class="docutils literal"><span class="pre">prometheus-oper-prometheus</span></tt></dt>
<dd>Prometheus 本体</dd>
<dt><tt class="docutils literal"><span class="pre">prometheus-oper-alermanager</span></tt></dt>
<dd>Alert Manager 本体</dd>
<dt><tt class="docutils literal"><span class="pre">prometheus-node-exporter</span></tt></dt>
<dd>ノードごとのメトリクス出力用 node exporter</dd>
<dt><tt class="docutils literal"><span class="pre">kube-state-metrics</span></tt></dt>
<dd>Kubernetes のオブジェクトごとのメトリクス出力用 exporter</dd>
<dt><tt class="docutils literal">grafana</tt></dt>
<dd>Prometheus のメトリクス可視化用の Grafana 本体</dd>
<dt><tt class="docutils literal"><span class="pre">prometheus-oper-operator</span></tt></dt>
<dd>Prometheus Operator 本体</dd>
</dl>
<p>みたいになっている。Prometheus Operator の主な役割は、カスタムリソースによる Prometheus / AlertManager の設定管理及び監視対象との接続になる。具体的にどのように設定を管理していくは、後で見ていくとして、とりあえずデプロイされたものを触ってみる。まず、Prometheus 本体を見てみる。<tt class="docutils literal">localhost</tt> で見たい場合は、プロキシ立てると良い:</p>
<pre class="literal-block">
kubectl proxy
</pre>
<p>で、</p>
<pre class="literal-block">
http://localhost:8001/api/v1/namespaces/prometheus/services/http:prometheus-prometheus-oper-prometheus:web/proxy/
</pre>
<p>にアクセスするといいだろう。Prometheus の画面が表示されて、色々ターゲットが追加されてるのが分かると思う。お試し環境だと etcd とかデプロイしてないと思うので、etcd が立ち上がってないとかアラートが出てると思うが、それらのアラートの調整の仕方は後で紹介する。<tt class="docutils literal">Grafana</tt> の画面も見てみるといいだろう。<tt class="docutils literal">Grafana</tt> の方は proxy から見るのはちょっときついので、ポートフォワードして見るといい:</p>
<pre class="literal-block">
kubectl port-forward service/prometheus-grafana 3000:80 --address 0.0.0.0 -n prometheus
</pre>
<p>Grafana の方はログインが必要で、ユーザ <tt class="docutils literal">admin</tt> / パスワード <tt class="docutils literal"><span class="pre">prom-operator</span></tt> で入れる。このパラメータは、<a class="reference external" href="https://github.com/helm/charts/tree/master/stable/prometheus-operator#grafana">チャートのパラメータ</a> として弄れるようになっている。Grafana も初期段階で色々テンプレートが追加されていて便利という感じ。</p>
</div>
<div class="section" id="auto-id-2">
<h2>カスタムリソース<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>これだけ見ると、まあ単に初期設定モリモリの Prometheus 周辺ツールがパッとデプロイできるだけとなるんだけど、Prometheus Operator の神髄はここから。Prometheus Operator は、Prometheus の設定をカスタムリソースとしてデプロイできる。まずは、どういうリソースがデプロイされているかを見てみる。以下の URL から Dashboard にアクセスする:</p>
<pre class="literal-block">
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:http/proxy/
</pre>
<p>そして、上のメニューから <tt class="docutils literal">prometheus</tt> ネームスペースを選択し、左のメニューの「カスタムリソース定義」欄を選択する。すると、幾つかの項目が表示されると思う。それぞれ、</p>
<dl class="docutils">
<dt>Prometheus</dt>
<dd>Prometheus ポッドのテンプレート。このテンプレートを基に operator が Prometheus ポッドをデプロイする。</dd>
<dt>Alertmanager</dt>
<dd>Alertmanager ポッドのテンプレート。このテンプレートを基に operator が Alertmanager ポッドをデプロイする。</dd>
<dt>PrometheusRule</dt>
<dd>Prometheus のルールを表すカスタムリソース</dd>
<dt>ThanosRuler</dt>
<dd>Thanos のルールを表すカスタムリソース (Thanos 触ったことないので、今回は割愛)</dd>
</dl>
<p>みたいなもの。後、<tt class="docutils literal">PodMonitor</tt> / <tt class="docutils literal">ServiceMonitor</tt> があるが、これは後述するので今は割愛する。Prometheus のルールを弄りたかったら PrometheusRule カスタムリソースをいじることになる。新規にルールを追加したかったら新しく PrometheusRule を作ってデプロイすればいいし、既存のものをいじりたかったら既存のカスタムリソースを弄ればいい。</p>
<p>試しに、etcd のアラートを消してみる。PrometheusRule カスタムリソースの欄に <tt class="docutils literal"><span class="pre">prometheus-prometheus-oper-etcd</span></tt> というカスタムリソースがある。定義を見てみると、<tt class="docutils literal">etcdMembersDown</tt> などのアラートルールが記載されてるのが分かると思う。このカスタムリソースでは etcd ターゲットに関するルールが規定されている。これを削除してみる:</p>
<pre class="literal-block">
kubectl -n prometheus delete prometheusrules prometheus-prometheus-oper-etcd
</pre>
<p>で、しばらく待ってから <a class="footnote-reference" href="#watch-completed-on-log" id="auto-id-3">[1]</a> Prometheus のダッシュボードをのぞいてみると、アラートから etcd 関連のルールが消えてることが確認できると思う。次は新しくルールを追加してみる。以下のカスタムリソースを作成する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">monitoring.coreos.com/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">PrometheusRule</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mysample-alert.rules</span>
<span class="w"> </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus</span>
<span class="w"> </span><span class="nt">labels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus-operator</span>
<span class="w"> </span><span class="nt">release</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">groups</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">mysample-alert.rules</span>
<span class="w"> </span><span class="nt">rules</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span>
<span class="w"> </span><span class="nt">alert</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">MyTargetDown</span>
<span class="w"> </span><span class="nt">expr</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">>-</span>
<span class="w"> </span><span class="no">100 * (count(up == 0) BY (job, namespace, service) / count(up) BY</span>
<span class="w"> </span><span class="no">(job, namespace, service)) > 10</span>
<span class="w"> </span><span class="nt">for</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">10m</span>
<span class="w"> </span><span class="nt">labels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">severity</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">warning</span>
<span class="w"> </span><span class="nt">annotations</span><span class="p">:</span>
<span class="w"> </span><span class="nt">message</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">>-</span>
<span class="w"> </span><span class="no">{{ $labels.job }}/{{ $labels.service }} targets in</span>
<span class="w"> </span><span class="no">{{ $labels.namespace }} namespace are down.</span>
</pre></div></td></tr></table></div>
<p>これを、例えば <tt class="docutils literal"><span class="pre">mysample-alert.rules.yaml</span></tt> として、</p>
<pre class="literal-block">
kubectl apply -f mysample-alert.rules.yaml
</pre>
<p>とやると、デプロイできる。後はしばらく待てば、Prometheus Dashboard のアラート一覧に、<tt class="docutils literal">MyTargetDown</tt> というアラートが追加されてることが分かる。このようにして新しいルールを追加したり、既存のルールを編集・削除したりできる。</p>
<p>ところで、上でデプロイしたルールの <tt class="docutils literal">labels</tt> で設定されてる <tt class="docutils literal">app</tt> / <tt class="docutils literal">release</tt> の値は、デフォルトでデプロイされている prometheus でセレクタとして設定されてる値で、これを設定しないとルールが認識されないようになっている。実際にその部分を見てみる。Prometheus カスタムリソースとして、1つだけデプロイされている <tt class="docutils literal"><span class="pre">prometheus-prometheus-oper-prometheus</span></tt> の設定をのぞいてみる。ここでは、</p>
<ul class="simple">
<li>接続する Alertmanager</li>
<li>ServiceMonitor / PodMonitor のセレクタ</li>
<li>PrometheusRule のセレクタ</li>
</ul>
<p>や、Prometheus ポッドの設定ができる。PrometheusRule のセレクタは、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">ruleNamespaceSelector</span><span class="p">:</span><span class="w"> </span><span class="p p-Indicator">{}</span>
<span class="nt">ruleSelector</span><span class="p">:</span>
<span class="w"> </span><span class="nt">matchLabels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus-operator</span>
<span class="w"> </span><span class="nt">release</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus</span>
</pre></div></td></tr></table></div>
<p>の部分がそうで、デフォルトの Prometheus ポッドでは <tt class="docutils literal">app</tt> が <tt class="docutils literal"><span class="pre">prometheus-operator</span></tt> で、<tt class="docutils literal">release</tt> が <tt class="docutils literal">prometheus</tt> のラベルを持っている PrometheusRule のみ認識され、Prometheus にルールとして取り込まれる。メトリクスによって監視サーバを分けたい場合などは、対応するルールにラベルを設定しておき、そのラベルに対するセレクタを設定した Prometheus カスタムリソースをデプロイすればいい。</p>
<p>Prometheus カスタムリソースから作られたポッドは、Prometheus のログがそのままログとして出ている。カスタムリソースで書いたルールが間違っていたら、ログにその旨が出力されるので、カスタムリソースがちゃんと設定されてるのにルールが反映されていない場合は確認してみるといい。カスタムリソースから作られた設定及びルールは、</p>
<ul class="simple">
<li><tt class="docutils literal">/etc/prometheus/config_out/prometheus.env.yaml</tt></li>
<li><tt class="docutils literal"><span class="pre">/etc/prometheus/rules/<pod名>/<rule名>.yaml</span></tt></li>
</ul>
<p>に入っている。ログでは正常に動いてそうなのに、ルールが反映されない場合次に確認するのが、カスタムリソースに対応するルールファイルがあるかとそのファイルの中身がちゃんと入っているかだ。大体それを確認すればトラブルシューティングができるはず。</p>
<p>Alertmanager カスタムリソースはちょっとめんどいので今回は省略する。<a class="reference external" href="https://github.com/coreos/prometheus-operator/blob/master/Documentation/user-guides/alerting.md">ドキュメント</a> を参照のこと。基本的には、Alertmanager カスタムリソースを作成し、対応する alertmanager の設定を secret で作成する。で、Prometheus カスタムリソースにその Alertmanager カスタムリソースと secret を指定するとアラートが設定できる。</p>
</div>
<div class="section" id="podmonitor-servicemonitor">
<h2><tt class="docutils literal">PodMonitor</tt> / <tt class="docutils literal">ServiceMonitor</tt><a class="headerlink" href="#podmonitor-servicemonitor" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、ルールの変更とポッドの設定はできたが、Prometheus の監視対象、つまりターゲットの変更はどうすればいいのだろう? そのターゲットの管理を担うのが <tt class="docutils literal">PodMonitor</tt> / <tt class="docutils literal">ServiceMonitor</tt> になる。それぞれ名前の通り、pod / service ごとのターゲットの設定ができる。</p>
<p>初期で追加されているターゲットは、それぞれ ServiceMonitor で設定されている。例えば、grafana の設定は、<tt class="docutils literal"><span class="pre">prometheus-prometheus-oper-grafana</span></tt> という名前のカスタムリソースがそれに当たる。中身は、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">endpoints</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span>
<span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/metrics</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">service</span>
<span class="w"> </span><span class="nt">namespaceSelector</span><span class="p">:</span>
<span class="w"> </span><span class="nt">matchNames</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span>
<span class="w"> </span><span class="nt">matchLabels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/instance</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">grafana</span>
</pre></div></td></tr></table></div>
<p>のような内容になっている。<tt class="docutils literal">namespaceSelector</tt> で <tt class="docutils literal">prometheus</tt> 名前空間、<tt class="docutils literal">selector</tt> でその名前空間のラベルでマッチするサービスを探すことになる。このセレクタに引っかかる service が、<tt class="docutils literal"><span class="pre">prometheus-grafana</span></tt> になる。その内容は、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ClusterIP</span>
<span class="w"> </span><span class="nt">ports</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">service</span>
<span class="w"> </span><span class="nt">protocol</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">TCP</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">80</span>
<span class="w"> </span><span class="nt">targetPort</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">3000</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/instance</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus</span>
<span class="w"> </span><span class="nt">app.kubernetes.io/name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">grafana</span>
</pre></div></td></tr></table></div>
<p>となっている。ServiceMonitor は、このサービスの <tt class="docutils literal">service</tt> という名前のポート、つまり 3000 番の <tt class="docutils literal">/metrics</tt> パスをターゲットとして設定する。このように <tt class="docutils literal">ServiceMonitor</tt> をデプロイしたり、編集することで、サービスに対してのターゲットを設定できる。試しに、etcd / proxy のターゲットがお試し環境だと機能していないので消してみる。それぞれ <tt class="docutils literal"><span class="pre">prometheus-prometheus-oper-kube-etcd</span></tt> / <tt class="docutils literal"><span class="pre">prometheus-prometheus-oper-kube-proxy</span></tt> という ServiceMonitor が対応している。これら2つを削除し、しばらく待つと、ターゲットからその2つが消えてることが確認できる。もちろん、自分でデプロイした exporter を持つサービスに対して自由にターゲットを設定できる。試しにやってみる。Kotlin で Spring Actuator を使ったメトリクス出力機能付き Web アプリを service としてデプロイし、その service に対して ServiceMonitor でメトリクスをターゲットとして追加してみる。</p>
<p>デプロイするサンプルアプリは、<a class="reference external" href="https://github.com/mizunashi-mana/kotlin-spring-actuator-sample">https://github.com/mizunashi-mana/kotlin-spring-actuator-sample</a> 。k8s のリソースも書いてあるので、それでまずデプロイをする:</p>
<pre class="literal-block">
git clone https://github.com/mizunashi-mana/kotlin-spring-actuator-sample
cd kotlin-spring-actuator-sample
./gradlew docker
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
</pre>
<p>これで、actuator のメトリクスが出されるようになる。そのメトリクスの内容は、</p>
<pre class="literal-block">
http://localhost:8001/api/v1/namespaces/default/services/http:spring-actuator-demo:web/proxy/actuator/prometheus
</pre>
<p>とかで見れる。これを ServiceMonitor で監視してみる。以下のようなリソースを書く:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">monitoring.coreos.com/v1</span>
<span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">ServiceMonitor</span>
<span class="nt">metadata</span><span class="p">:</span>
<span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">spring-actuator-demo-monitor</span>
<span class="w"> </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus</span>
<span class="w"> </span><span class="nt">labels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">release</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">prometheus</span>
<span class="nt">spec</span><span class="p">:</span>
<span class="w"> </span><span class="nt">namespaceSelector</span><span class="p">:</span>
<span class="w"> </span><span class="nt">any</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">true</span>
<span class="w"> </span><span class="nt">selector</span><span class="p">:</span>
<span class="w"> </span><span class="nt">matchLabels</span><span class="p">:</span>
<span class="w"> </span><span class="nt">app</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">spring-actuator-demo</span>
<span class="w"> </span><span class="nt">endpoints</span><span class="p">:</span>
<span class="w"> </span><span class="p p-Indicator">-</span>
<span class="w"> </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">web</span>
<span class="w"> </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">/actuator/prometheus</span>
</pre></div></td></tr></table></div>
<p>で、例えば <tt class="docutils literal"><span class="pre">demo-service-monitor.yaml</span></tt> として、デプロイする:</p>
<pre class="literal-block">
kubectl apply -f demo-service-monitor.yaml
</pre>
<p>で、しばらく待ってから Prometheus のターゲットを確認すると、<tt class="docutils literal"><span class="pre">spring-actuator-demo</span></tt> のためのターゲットが確認できると思う。実際にメトリクスが取れてるかは、Grafana にポートフォワードして、</p>
<pre class="literal-block">
http://localhost:3000/explore?orgId=1&left=%5B%22now-1h%22,%22now%22,%22Prometheus%22,%7B%22expr%22:%22jvm_buffer_memory_used_bytes%22%7D,%7B%22mode%22:%22Metrics%22%7D,%7B%22ui%22:%5Btrue,true,true,%22none%22%5D%7D%5D
</pre>
<p>とかで確認してみるといいだろう。デフォルトでデプロイされてる Prometheus カスタムリソースは、<tt class="docutils literal">release: prometheus</tt> ラベルで PodMonitor / ServiceMonitor を探すので、そのラベルは設定する必要がある。それから、ターゲットのジョブラベルは明示的に設定することもできるが、指定しない場合は <tt class="docutils literal">name</tt> が設定される。Prometheus では同じジョブを持つメトリクスを複数登録できないので、monitor の <tt class="docutils literal">name</tt> は注意して設定しておくといいだろう。</p>
<p>今回のは service ごとにセレクトしてターゲットに設定をするが、pod ごとにセレクトできるのが PodMonitor になる。こちらは使い方は ServiceMonitor と同じで、pod のセレクトか service のセレクトかだけが異なるので、今回は省略する。</p>
</div>
<div class="section" id="auto-id-5">
<h2>まとめ<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、Prometheus Operator の使い方を紹介した。Prometheus Operator は Kubernetes 上での監視体制を整えるためのパッケージで、カスタムリソースで監視対象を追加したりルールを追加したりできる。監視対象の追加は Kubernetes のエコシステムに合わせた形で定義できるため、結構便利。ただ、現状は beta 版なのでこの先大きく使い方が変わる可能性がある。そこは注意した方がいいだろう。今回はそういう感じで。</p>
<table class="docutils footnote" frame="void" id="watch-completed-on-log" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[1]</a></td><td>反映の完了は各 prometheus ポッドのログから確認できる。<tt class="docutils literal">Completed loading of configuration file</tt> というログが出たら反映が行われている。</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/07/prometheus-operator.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/07/prometheus-operator.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>CBC mode に対しての Padding Oracle Attack2020-07-19T13:33:47+09:002022-12-27T14:31:47+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-07-19:/blog/posts/2020/07/padding-oracle-attack/<p>共通鍵暗号の暗号方式としてよく用いられている暗号の種類として,ブロック暗号がある.ブロック暗号は,暗号方式 …</p><p>共通鍵暗号の暗号方式としてよく用いられている暗号の種類として,ブロック暗号がある.ブロック暗号は,暗号方式の大別で,固定長のデータを単位として処理するような暗号の総称である.ところで,もちろん暗号化の対象となるデータは,固定長とは限らないし,かなり長さが大きくなる場合もある.そこで,ブロック暗号を扱うデータサイズより長いデータに対しても利用できるよう補佐する暗号利用モードと呼ばれるメカニズムも用意されている.</p>
<p>ところで,この暗号利用モードは,誤って利用すると,元となったブロック暗号が優秀であろうと致命的に安全性が損なわれる場合が多いことが知られている.今回はそのケースのうち,CBC と呼ばれる暗号利用モードについて知られている攻撃手法,padding oracle attack の概要を見ていく.</p>
<div class="section" id="cbc-cipher-block-chaining">
<h2>CBC (Cipher Block Chaining)<a class="headerlink" href="#cbc-cipher-block-chaining" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ブロック暗号として,</p>
<ul class="simple">
<li>暗号化アルゴリズム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>E</mi><mi>K</mi></msub><mo>:</mo><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup><mo>→</mo><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">E_K: \Sigma^n \to \Sigma^n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span></span></li>
<li>複合アルゴリズム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>D</mi><mi>K</mi></msub><mo>:</mo><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup><mo>→</mo><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">D_K: \Sigma^n \to \Sigma^n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p>があったとする.ここで,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">\Sigma^n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span></span> は入出力として考えられる長さ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> の文字列の集合,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>K</mi></mrow><annotation encoding="application/x-tex">K</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span></span></span> は鍵である.これを任意の長さの文字列 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo>∈</mo><msup><mi mathvariant="normal">Σ</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">P \in \Sigma^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6887em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span> に適用することを考える.つまり,</p>
<ul class="simple">
<li>暗号化アルゴリズム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>E</mi><mi>K</mi><mo>+</mo></msubsup><mo>:</mo><msup><mi mathvariant="normal">Σ</mi><mo>∗</mo></msup><mo>→</mo><msup><mi mathvariant="normal">Σ</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">E^+_K: \Sigma^* \to \Sigma^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2935em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6887em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6887em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span></li>
<li>複合アルゴリズム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>D</mi><mi>K</mi><mo>+</mo></msubsup><mo>:</mo><msup><mi mathvariant="normal">Σ</mi><mo>∗</mo></msup><mo>→</mo><msup><mi mathvariant="normal">Σ</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">D^+_K: \Sigma^* \to \Sigma^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2935em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6887em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6887em;"></span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p>を作りたい.さて,状況を簡単にするため,入出力の長さがブロック長 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> の倍数になっている状況を考える.この時,入出力は長さ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> の文字列 (ブロック) の列と考えられる.つまり,</p>
<ul class="simple">
<li>暗号化アルゴリズム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>E</mi><mi>K</mi><mo>+</mo></msubsup><mo>:</mo><mo stretchy="false">(</mo><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup><msup><mo stretchy="false">)</mo><mo>∗</mo></msup><mo>→</mo><mo stretchy="false">(</mo><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup><msup><mo stretchy="false">)</mo><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">E^+_K: (\Sigma^n)^* \to (\Sigma^n)^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2935em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span></li>
<li>複合アルゴリズム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>D</mi><mi>K</mi><mo>+</mo></msubsup><mo>:</mo><mo stretchy="false">(</mo><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup><msup><mo stretchy="false">)</mo><mo>∗</mo></msup><mo>→</mo><mo stretchy="false">(</mo><msup><mi mathvariant="normal">Σ</mi><mi>n</mi></msup><msup><mo stretchy="false">)</mo><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">D^+_K: (\Sigma^n)^* \to (\Sigma^n)^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2935em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord">Σ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p>が作れれば,その列を平坦にしたものを入出力の文字列として捉えることで,ブロック暗号を拡張できる.で,その拡張方法だが,単純に思いつくのは以下のようなものだ:</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>E</mi><mi>K</mi><mo>+</mo></msubsup><mo>=</mo><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub><mo>↦</mo><mo stretchy="false">{</mo><msub><mi>E</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>P</mi><mi>i</mi></msub><mo stretchy="false">)</mo><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">E^+_K = \{P_i\}_{i \in [m]} \mapsto \{E_K(P_i)\}_{i \in [m]}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2935em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>D</mi><mi>K</mi><mo>+</mo></msubsup><mo>=</mo><mo stretchy="false">{</mo><msub><mi>C</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub><mo>↦</mo><mo stretchy="false">{</mo><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>C</mi><mi>i</mi></msub><mo stretchy="false">)</mo><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">D^+_K = \{C_i\}_{i \in [m]} \mapsto \{D_K(C_i)\}_{i \in [m]}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2935em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p>つまり,単純に各ブロックにそのまま元のブロック暗号を適用する方法だ.この方法は ECB モードと呼ばれている.ただ,この方法は</p>
<ul class="simple">
<li>同じブロックは同じブロックに暗号化されるため,暗号文を見て同じブロックの箇所が判定できる</li>
<li>ブロック単位で複製・削除・順序入れ替えなどの改竄ができる</li>
</ul>
<p>と言った問題がある.そのため,もう少し改良を加えたい.ECB の問題点は,主にそれぞれのブロックが独立に扱われていることに由来する.そこで,それぞれのブロックに対して他のブロックの内容に依存するようなベクトルを注入することが考えられる.CBC モードは,この注入を XOR で行うようなモードになる.</p>
<p>CBC モードは,初期ベクトル <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mi>v</mi></mrow><annotation encoding="application/x-tex">\mathit{Iv}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathit">Iv</span></span></span></span></span></span> が与えられた時,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>E</mi><mi>K</mi><mo>+</mo></msubsup><mo>=</mo><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub><mo>↦</mo><mo stretchy="false">{</mo><msub><mi>C</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">{</mo><mn>0</mn><mo stretchy="false">}</mo><mo>∪</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">
E^+_K = \{P_i\}_{i \in [m]} \mapsto \{C_i\}_{i \in \{0\} \cup [m]}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2837em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8213em;"><span style="top:-2.4163em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2837em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">{</span><span class="mord mtight">0</span><span class="mclose mtight">}</span><span class="mbin mtight">∪</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mi>i</mi></msub><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>I</mi><mi>v</mi></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>i</mi><mo>=</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>E</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>P</mi><mi>i</mi></msub><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
C_i = \left\{\begin{array}{ll}
\mathit{Iv} &(i = 0) \\
E_K(P_i \oplus C_{i - 1}) &(\text{otherwise})
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">Iv</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>D</mi><mi>K</mi><mo>+</mo></msubsup><mo>=</mo><mo stretchy="false">{</mo><msub><mi>C</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">{</mo><mn>0</mn><mo stretchy="false">}</mo><mo>∪</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub><mo>↦</mo><mo stretchy="false">{</mo><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>C</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">
D^+_K = \{C_i\}_{i \in \{0\} \cup [m]} \mapsto \{D_K(C_i) \oplus C_{i - 1}\}_{i \in [m]}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2837em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8213em;"><span style="top:-2.4163em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2837em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">{</span><span class="mord mtight">0</span><span class="mclose mtight">}</span><span class="mbin mtight">∪</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span></div>
<p>というような拡張を施す.一応よくある図を,NIST の資料から拝借して掲載しておく <a class="footnote-reference" href="#nist-block-cipher-modes" id="auto-id-1">[1]</a>:</p>
<img alt="CBC モードのイメージ図" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2020/07/padding-oracle-attack/padding-oracle-attack/cbc-image.png"/>
<p>最初は初期ベクトルが注入され,その後は一つ前のブロックの暗号文がベクトルとして注入されるようになる.これにより,EBC と異なり各ブロックはそれ以前のブロックの内容に依存するようになる.さて,このモードの正当性は,以下のように確かめられる:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msubsup><mi>D</mi><mi>K</mi><mo>+</mo></msubsup><mo stretchy="false">(</mo><msubsup><mi>E</mi><mi>K</mi><mo>+</mo></msubsup><mo stretchy="false">(</mo><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">{</mo><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>E</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>P</mi><mi>i</mi></msub><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo stretchy="false">)</mo><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><mo>⊕</mo><mo stretchy="false">(</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo stretchy="false">)</mo><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><mo>⊕</mo><mn>0</mn><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{ll}
D^+_K(E^+_K(\{P_i\}_{i \in [m]}))
&= \{D_K(E_K(P_i \oplus C_{i - 1}) \oplus C_{i - 1}\}_{i \in [m]} \\
&= \{P_i \oplus C_{i - 1} \oplus C_{i - 1}\}_{i \in [m]} \\
&= \{P_i \oplus (C_{i - 1} \oplus C_{i - 1})\}_{i \in [m]} \\
&= \{P_i \oplus 0\}_{i \in [m]} \\
&= \{P_i\}_{i \in [m]}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:6em;vertical-align:-2.75em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span><span class="mopen">({</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mclose">))</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">0</span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>このように,最終的に暗号化と復号で注入したベクトルが XOR によりうまく打ち消し合い,最終的に平文に戻る.これが CBC モードの概要になる.</p>
<p>ところで,CBC モードを利用するには,入力の長さがブロック長の倍数になっていないといけなかった.ブロック長は AES では 128bit,つまり 16byte になる.つまり,AES を CBC モードで利用するには,入力のバイト数が 16 の倍数である必要がある.これは不便なので,パディングを埋め込む運用が通常取られている.</p>
<p>よく用いられている方法が,PKCS#7 由来の方法 <a class="footnote-reference" href="#rfc-5652" id="auto-id-2">[2]</a> で,足りないバイト数分そのバイト数に相当する整数を埋めると言う方法だ.今回の例で言えば,例えば</p>
<pre class="literal-block">
30 31 32 33 34 35 36 37 38 39 40 41
</pre>
<p>というような 12 byte のデータに対して,パディングを埋めたい場合,足りないバイト数は 4 バイトなので,</p>
<pre class="literal-block">
30 31 32 33 34 35 36 37 38 39 40 41 42 04 04 04 04
</pre>
<p>というように 4 byte 分 4 を埋める.ところで,パディングを埋め込む場合,元データとパディングを区別できる必要がある.ただ,バイト数が 16 の倍数になっている場合パディングを埋め込まないようにすると,パディングが埋め込まれた結果のデータなのか,それともパディングが何も埋め込まれていない場合のデータなのかが分からない.そこで,パディングを埋め込む必要がない場合,つまりバイト数が 16 の倍数になっている場合も新しくパディングのみで構成されたブロックを追加するようにする.例えば,</p>
<pre class="literal-block">
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
</pre>
<p>というようなデータの場合は,</p>
<pre class="literal-block">
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
</pre>
<p>のように 16 (16進数表記で 10) を 16byte 分末尾に足す.これにより,全てのデータは必ずパディングが埋め込まれており,データの末尾を見れば何バイト分がパディングか分かるようになるため,パディングと元データを区別することができるようになる.</p>
<p>CBC モードを使用する場合は,上記のようなパディングを埋め込んでバイト数をブロック長の倍数にし,それから暗号化を行う.また,復号した後はパディングを取り除くことで多くの場合運用されている.</p>
</div>
<div class="section" id="padding-oracle-attack">
<h2>Padding Oracle Attack<a class="headerlink" href="#padding-oracle-attack" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>このパディングによる運用をつくことで,CBC モードにより暗号化された文を解読する攻撃が,padding oracle attack である.</p>
<p>CBC では,平文 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">\{P_i\}_{i \in [m]}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span>,その暗号文 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><msub><mi>C</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">{</mo><mn>0</mn><mo stretchy="false">}</mo><mo>∪</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">\{C_i\}_{i \in \{0\} \cup [m]}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">{</span><span class="mord mtight">0</span><span class="mclose mtight">}</span><span class="mbin mtight">∪</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span> について,以下の関係が成り立つ:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>C</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo>⊕</mo><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>E</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>P</mi><mi>i</mi></msub><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>⊕</mo><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><msub><mi>P</mi><mi>i</mi></msub><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo>⊕</mo><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">
D_K(C_i) \oplus C' = D_K(E_K(P_i \oplus C_{i - 1})) \oplus C' = P_i \oplus C_{i - 1} \oplus C'
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<p>ここで,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>C</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo>⊕</mo><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">
P' = D_K(C_i) \oplus C'
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<p>とおくと,平文 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">P_i</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> に対して,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mi>i</mi></msub><mo>=</mo><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>⊕</mo><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo>⊕</mo><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">
P_i = P' \oplus C_{i - 1} \oplus C'
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8852em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<p>という関係が求まる.つまり,何かブロック <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> があった時,それに対応する <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> が求まれば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">i - 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7429em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> 番目の暗号ブロックから <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span></span> 番目の平文を復元することが可能になる.もちろん,鍵 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>K</mi></mrow><annotation encoding="application/x-tex">K</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span></span></span> とアルゴリズム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が分かっていれば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> はそのまま求まる.しかし,攻撃側は普通鍵を知らないため,この攻撃を成功させるには <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を何らかの方法で求める必要がある.ところで,もし攻撃対象のアプリケーションが複合時パディング情報が合っているかを検証し,わざわざ検証結果を教えてくれる場合,実は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を求めることができる.padding oracle attack の名前の由来は,攻撃対象が padding oracle,つまり padding が合っているかをわざわざ教えてくれる機能を持つ場合に,攻撃できる手法ということだ.</p>
<p>さて,では具体的にどうするかだが,この攻撃では <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を求める式が復号処理とよく似ていることに着目する.つまり,復号機に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><msub><mi>C</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">C' C_i</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9019em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を送ってみると,復号機はそれをちゃんとした暗号文だと思い <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>C</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo>⊕</mo><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">D_K(C_i) \oplus C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を計算するはずだ.これは <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> と同じになる.ところで,先ほどの <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">P_i</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を復元する式では,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> が関係を守っているならば何でも良かった.そこで,この攻撃では最終的に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> が,</p>
<pre class="literal-block">
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
</pre>
<p>つまり,パディングのみになるような <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を探す.この探索は最後の 1byte から順に探していく.</p>
<p>今回は,攻撃対象はわざわざパディングが合っているかを検証しその結果を教えてくれるという機能,padding oracle を持っていた.そこで,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を中身は適当に設定し,最後の 1byte だけ順に 0 から 255 まで変えながら,padding oracle に送りつける.この時,padding oracle がパディングが正当であるという結果を返してくるということは,</p>
<ul class="simple">
<li>たまたまパディングが正当な <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を設定できた</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> の最後が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>01</mn></mrow><annotation encoding="application/x-tex">01</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">01</span></span></span></span></span> になった</li>
</ul>
<p>の2択になる.ここでは,後者になるよううまく <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を調整できていると仮定する.さて,この <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を使うと,実は最後の byte を自由にいじることができる.例えば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> の最後のバイト <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>C</mi><mn>16</mn><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup></mrow><annotation encoding="application/x-tex">C'_{16}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.2481em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4519em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">16</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span></span></span></span></span> に対して <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>C</mi><mn>16</mn><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo>⊕</mo><mn>01</mn><mo>⊕</mo><mn>02</mn></mrow><annotation encoding="application/x-tex">C'_{16} \oplus 01 \oplus 02</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.2481em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4519em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">16</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">01</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">02</span></span></span></span></span> としたものを新たに <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mrow><mo mathvariant="normal">′</mo><mo mathvariant="normal">′</mo></mrow></msup></mrow><annotation encoding="application/x-tex">C''</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′′</span></span></span></span></span></span></span></span></span></span></span></span></span> とおくと,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>C</mi><mi>i</mi></msub><msub><mo stretchy="false">)</mo><mn>16</mn></msub><mo>⊕</mo><msubsup><mi>C</mi><mn>16</mn><mrow><mo mathvariant="normal">′</mo><mo mathvariant="normal">′</mo></mrow></msubsup><mo>=</mo><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>C</mi><mi>i</mi></msub><msub><mo stretchy="false">)</mo><mn>16</mn></msub><mo>⊕</mo><msubsup><mi>C</mi><mn>16</mn><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo>⊕</mo><mn>01</mn><mo>⊕</mo><mn>02</mn><mo>=</mo><mo stretchy="false">(</mo><mn>01</mn><mo>⊕</mo><mn>01</mn><mo stretchy="false">)</mo><mo>⊕</mo><mn>02</mn><mo>=</mo><mn>02</mn></mrow><annotation encoding="application/x-tex">
D_K(C_i)_{16} \oplus C''_{16} = D_K(C_i)_{16} \oplus C'_{16} \oplus 01 \oplus 02 = (01 \oplus 01) \oplus 02 = 02
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">16</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0489em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">16</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">16</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0489em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">16</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">01</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">02</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">01</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">01</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">02</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">02</span></span></span></span></span></div>
<p>となる.後は,これにより最後が <tt class="docutils literal">02</tt> となる <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> が得られるので,その <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> をベースにまた最後から 2byte 目を変遷させて padding oracle に送りつけ,パディングが正当になる,つまり <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> の最後が <tt class="docutils literal">02 02</tt> になるような <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> を探す.これを順に最初のバイトまで繰り返すと,最終的に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> が</p>
<pre class="literal-block">
10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10
</pre>
<p>となるような <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> が得られることになる.後は,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> との関係を守る <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> が得られたので,それを使って平文を復元すればいい.</p>
</div>
<div class="section" id="auto-id-3">
<h2>実際に攻撃してみる<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,ところで padding oracle をわざわざ提供してくれるアプリケーションは存在するんだろうか? ここでは,「わざわざ」とわざとらしく言っているが,実際には意識せず padding oracle を提供してしまう場合がある.多くの場合,サーバの返すエラーの種類が複数ある場合だ.多くの言語が提供する暗号化インターフェースでは,padding の不整合はそれ専用のエラーが出される.例えば Ruby では,</p>
<pre class="literal-block">
bad decrypt (OpenSSL::Cipher::CipherError)
</pre>
<p>というようなエラーになる.Java では専用の例外 <a class="reference external" href="https://docs.oracle.com/en/java/javase/14/docs/api/java.base/javax/crypto/BadPaddingException.html">BadPaddingException</a> が用意されていて,こいつが投げられる.これらをもし,復号された後の文に対するバリデーションとは異なる例外ハンドリングで処理し,結果を異なる形 (例えばエラーメッセージをそのまま返すなど) でユーザに表示してしまうと,padding oracle ができてしまうことになる.</p>
<p>では,実際に padding oracle のあるサービスに対して攻撃をしてみる.今回は簡易的に,Ruby の以下のメソッドに対して攻撃を行う:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span></pre></div></td><td class="code"><div><pre><span></span><span class="nb">require</span><span class="w"> </span><span class="s1">'openssl'</span>
<span class="vg">$n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">16</span>
<span class="k">def</span><span class="w"> </span><span class="nf">encrypt</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="w"> </span><span class="n">enc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">OpenSSL</span><span class="o">::</span><span class="no">Cipher</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">"AES-256-CBC"</span><span class="p">)</span>
<span class="w"> </span><span class="n">enc</span><span class="o">.</span><span class="n">encrypt</span>
<span class="w"> </span><span class="n">enc</span><span class="o">.</span><span class="n">key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'secret key'</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span>
<span class="w"> </span><span class="n">iv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'CBC IV'</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="vg">$n</span><span class="p">)</span>
<span class="w"> </span><span class="n">enc</span><span class="o">.</span><span class="n">iv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">iv</span>
<span class="w"> </span><span class="n">iv</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">enc</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">data</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">enc</span><span class="o">.</span><span class="n">final</span>
<span class="k">end</span>
<span class="k">def</span><span class="w"> </span><span class="nf">decrypt</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="w"> </span><span class="nb">sleep</span><span class="p">(</span><span class="mi">0</span><span class="o">.</span><span class="mo">01</span><span class="p">)</span>
<span class="w"> </span><span class="n">dec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="no">OpenSSL</span><span class="o">::</span><span class="no">Cipher</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">"AES-256-CBC"</span><span class="p">)</span>
<span class="w"> </span><span class="n">dec</span><span class="o">.</span><span class="n">decrypt</span>
<span class="w"> </span><span class="n">dec</span><span class="o">.</span><span class="n">key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'secret key'</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">32</span><span class="p">)</span>
<span class="w"> </span><span class="n">dec</span><span class="o">.</span><span class="n">iv</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">data</span><span class="o">[</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="vg">$n</span><span class="o">]</span>
<span class="w"> </span><span class="n">dec</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">data</span><span class="o">[</span><span class="vg">$n</span><span class="p">,</span><span class="w"> </span><span class="n">data</span><span class="o">.</span><span class="n">length</span><span class="o">]</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">dec</span><span class="o">.</span><span class="n">final</span>
<span class="k">end</span>
<span class="k">def</span><span class="w"> </span><span class="nf">valid_padding?</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="w"> </span><span class="k">begin</span>
<span class="w"> </span><span class="n">decrypt</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="w"> </span><span class="kp">true</span>
<span class="w"> </span><span class="k">rescue</span><span class="w"> </span><span class="no">OpenSSL</span><span class="o">::</span><span class="no">Cipher</span><span class="o">::</span><span class="no">CipherError</span>
<span class="w"> </span><span class="kp">false</span>
<span class="w"> </span><span class="k">end</span>
<span class="k">end</span>
</pre></div></td></tr></table></div>
<p>攻撃側が使用できるのは,<tt class="docutils literal">valid_padding?</tt> メソッドのみである.気分を出すため,<tt class="docutils literal">decrypt</tt> は 0.01 秒のレイテンシが出るようにしているが,これはまあ本質的ではないので無視してもらって良い.では,実際に攻撃側を実装していく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">attack</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="w"> </span><span class="n">cs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">data</span><span class="o">.</span><span class="n">scan</span><span class="p">(</span><span class="sr">/[\s\S]{</span><span class="si">#{</span><span class="vg">$n</span><span class="si">}</span><span class="sr">}/</span><span class="p">)</span>
<span class="w"> </span><span class="n">ps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">[]</span>
<span class="w"> </span><span class="p">(</span><span class="n">cs</span><span class="o">.</span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">downto</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="w"> </span><span class="n">pre_c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cs</span><span class="o">[</span><span class="n">i</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="o">]</span>
<span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cs</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="n">plain</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'?'</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="vg">$n</span>
<span class="w"> </span><span class="n">c_dash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"</span><span class="se">\x00</span><span class="s2">"</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="vg">$n</span>
<span class="w"> </span><span class="n">is_illegal</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">true</span>
<span class="w"> </span><span class="nb">puts</span><span class="w"> </span><span class="s2">"Start detecting </span><span class="si">#{</span><span class="n">i</span><span class="si">}</span><span class="s2">th block..."</span>
<span class="w"> </span><span class="mi">1</span><span class="o">.</span><span class="n">upto</span><span class="p">(</span><span class="vg">$n</span><span class="p">)</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="o">|</span><span class="n">j</span><span class="o">|</span>
<span class="w"> </span><span class="mi">0</span><span class="o">.</span><span class="n">upto</span><span class="p">(</span><span class="mi">255</span><span class="p">)</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="o">|</span><span class="n">k</span><span class="o">|</span>
<span class="w"> </span><span class="n">c_dash</span><span class="o">[-</span><span class="n">j</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">k</span><span class="o">.</span><span class="n">chr</span>
<span class="w"> </span><span class="nb">print</span><span class="w"> </span><span class="s1">'.'</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">valid_padding?</span><span class="p">(</span><span class="n">c_dash</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">c</span><span class="p">)</span>
<span class="w"> </span><span class="n">plain</span><span class="o">[-</span><span class="n">j</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">c_dash</span><span class="o">.</span><span class="n">bytes</span><span class="o">[-</span><span class="n">j</span><span class="o">]</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">pre_c</span><span class="o">.</span><span class="n">bytes</span><span class="o">[-</span><span class="n">j</span><span class="o">]</span><span class="p">)</span><span class="o">.</span><span class="n">chr</span>
<span class="w"> </span><span class="n">c_dash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">c_dash</span><span class="o">.</span><span class="n">bytes</span><span class="o">.</span><span class="n">map</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">|</span><span class="n">x</span><span class="o">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s1">'C*'</span><span class="p">)</span>
<span class="w"> </span><span class="n">is_illegal</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">false</span>
<span class="w"> </span><span class="nb">puts</span><span class="w"> </span><span class="o"><<~</span><span class="dl">EOS</span>
<span class="sh"> detected #{$n - j}th byte!</span>
<span class="sh"> P: #{plain.inspect}</span>
<span class="sh"> C': #{c_dash.inspect}</span>
<span class="dl"> EOS</span>
<span class="w"> </span><span class="k">break</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">is_illegal</span>
<span class="w"> </span><span class="k">raise</span><span class="w"> </span><span class="s2">"Something illegal happend!"</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">ps</span><span class="o">.</span><span class="n">unshift</span><span class="p">(</span><span class="n">plain</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">ps</span><span class="o">.</span><span class="n">join</span>
<span class="k">end</span>
</pre></div></td></tr></table></div>
<p>基本的には,確認用出力以外は上記で述べたアルゴリズムをそのまま実装するだけだ.ただ平文の復元は,1byte ごとの <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> の値が分かればそれぞれのバイトごとに復元可能なので,見やすいよう 1byte ごとに復元している.これで,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">plain_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"This is a sample text to crypt by AES-CBC."</span>
<span class="n">cipher_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">encrypt</span><span class="p">(</span><span class="n">plain_data</span><span class="p">)</span>
<span class="nb">p</span><span class="w"> </span><span class="n">cipher_data</span>
<span class="nb">p</span><span class="w"> </span><span class="n">attack</span><span class="p">(</span><span class="n">cipher_data</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>というようなプログラムを走らせれば,最終的に</p>
<pre class="literal-block">
"CBC IV St\xD7\xF0V\xADf\x05\xDB\x04\xAE\xE7/-\xF8\xC8\x91\xCFFL\xD8\xD8\xDD\x0F\xD3\xBC\b\xCBa]ZO\xAA\x06@F;g\x14\x81s\xF4_\x0E\x85\x15_\x1A"
Start detecting 3th block...
........detected 15th byte!
P: "???????????????\u0006"
C': "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03K"
..........detected 14th byte!
P: "??????????????\u0006\u0006"
...
....detected 1th byte!
P: "?his is a sample"
C': "\x11::Cy/C\x10Q\x10CQ]@\\U"
.detected 0th byte!
P: "This is a sample"
C': "\x06;;Bx.B\x11P\x11BP\\A]T"
"This is a sample text to crypt by AES-CBC.\u0006\u0006\u0006\u0006\u0006\u0006"
</pre>
<p>というような出力が得られ,攻撃が成功することが確かめられる.</p>
</div>
<div class="section" id="encryption-attack">
<h2>Encryption Attack<a class="headerlink" href="#encryption-attack" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ここまでは暗号文の解読に焦点を当ててきたが,同様の方法で改竄も可能だ.まず,パディングがちゃんと付けられた平文 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">\{P_i\}_{i \in [m]}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span> があるとして,これを暗号化して送りつけたいとする.攻撃側は鍵を知らないので,これを他の方法でちゃんとした暗号文にする必要がある.</p>
<p>さて,平文に余分に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">P_{m + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span></span> を付け加えた <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><msub><mi>P</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">[</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">\{P_i\}_{i \in [m + 1]}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span> を考える.そして,そのちゃんとした暗号文を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><msub><mi>C</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mi>i</mi><mo>∈</mo><mo stretchy="false">{</mo><mn>0</mn><mo stretchy="false">}</mo><mo>∪</mo><mo stretchy="false">[</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo></mrow></msub></mrow><annotation encoding="application/x-tex">\{C_i\}_{i \in \{0\} \cup [m + 1]}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">∈</span><span class="mopen mtight">{</span><span class="mord mtight">0</span><span class="mclose mtight">}</span><span class="mbin mtight">∪</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span> とおいた時,前の</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><msub><mi>D</mi><mi>K</mi></msub><mo stretchy="false">(</mo><msub><mi>C</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo>⊕</mo><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">
P' = D_K(C_i) \oplus C'
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<p>を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> が見つかれば,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo>=</mo><msub><mi>P</mi><mi>i</mi></msub><mo>⊕</mo><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>⊕</mo><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">
C_{i - 1} = P_i \oplus P' \oplus C'
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8852em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<p>という関係が成り立つことになる.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>P</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">P'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>C</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">C'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> は上記の padding oracle attack の手法をそのまま使えば求められ,これによりある平文のブロックからその前のブロックに対応する暗号文が見つけられることになる.最終的に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">C_{m + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span></span> 以外の暗号ブロックを求めることができ,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">C_{m + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span></span> は余分に付け加えたブロックに対応する暗号文なので,それを取り除けば元の平文に対する暗号文が得られる.</p>
<p>実際に実装してみると,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">encrypt_attack</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="w"> </span><span class="n">pad_len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="vg">$n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">data</span><span class="o">.</span><span class="n">length</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="vg">$n</span>
<span class="w"> </span><span class="n">pad_len</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="vg">$n</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">pad_len</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">ps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">data</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">pad_len</span><span class="o">.</span><span class="n">chr</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">pad_len</span><span class="p">)</span>
<span class="w"> </span><span class="o">.</span><span class="n">scan</span><span class="p">(</span><span class="sr">/[\s\S]{</span><span class="si">#{</span><span class="vg">$n</span><span class="si">}</span><span class="sr">}/</span><span class="p">)</span>
<span class="w"> </span><span class="n">ps</span><span class="o">.</span><span class="n">push</span><span class="p">(</span><span class="s2">"</span><span class="se">\x00</span><span class="s2">"</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="vg">$n</span><span class="p">)</span>
<span class="w"> </span><span class="n">cs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">[</span><span class="s2">"</span><span class="se">\x00</span><span class="s2">"</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="vg">$n</span><span class="o">]</span>
<span class="w"> </span><span class="p">(</span><span class="n">ps</span><span class="o">.</span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">downto</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="w"> </span><span class="n">plain</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ps</span><span class="o">[</span><span class="n">i</span><span class="o">]</span>
<span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cs</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span>
<span class="w"> </span><span class="n">pre_c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"?"</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="vg">$n</span>
<span class="w"> </span><span class="n">c_dash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"</span><span class="se">\x00</span><span class="s2">"</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="vg">$n</span>
<span class="w"> </span><span class="n">is_illegal</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">true</span>
<span class="w"> </span><span class="nb">puts</span><span class="w"> </span><span class="s2">"Start detecting </span><span class="si">#{</span><span class="n">i</span><span class="si">}</span><span class="s2">th block..."</span>
<span class="w"> </span><span class="mi">1</span><span class="o">.</span><span class="n">upto</span><span class="p">(</span><span class="vg">$n</span><span class="p">)</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="o">|</span><span class="n">j</span><span class="o">|</span>
<span class="w"> </span><span class="mi">0</span><span class="o">.</span><span class="n">upto</span><span class="p">(</span><span class="mi">255</span><span class="p">)</span><span class="w"> </span><span class="k">do</span><span class="w"> </span><span class="o">|</span><span class="n">k</span><span class="o">|</span>
<span class="w"> </span><span class="n">c_dash</span><span class="o">[-</span><span class="n">j</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">k</span><span class="o">.</span><span class="n">chr</span>
<span class="w"> </span><span class="nb">print</span><span class="w"> </span><span class="s1">'.'</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">valid_padding?</span><span class="p">(</span><span class="n">c_dash</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">c</span><span class="p">)</span>
<span class="w"> </span><span class="n">pre_c</span><span class="o">[-</span><span class="n">j</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">plain</span><span class="o">.</span><span class="n">bytes</span><span class="o">[-</span><span class="n">j</span><span class="o">]</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">c_dash</span><span class="o">.</span><span class="n">bytes</span><span class="o">[-</span><span class="n">j</span><span class="o">]</span><span class="p">)</span><span class="o">.</span><span class="n">chr</span>
<span class="w"> </span><span class="n">c_dash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">c_dash</span><span class="o">.</span><span class="n">bytes</span><span class="o">.</span><span class="n">map</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">|</span><span class="n">x</span><span class="o">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="o">.</span><span class="n">pack</span><span class="p">(</span><span class="s1">'C*'</span><span class="p">)</span>
<span class="w"> </span><span class="n">is_illegal</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kp">false</span>
<span class="w"> </span><span class="nb">puts</span><span class="w"> </span><span class="o"><<~</span><span class="dl">EOS</span>
<span class="sh"> detected #{$n - j}th byte!</span>
<span class="sh"> C: #{pre_c.inspect}</span>
<span class="sh"> C': #{c_dash.inspect}</span>
<span class="dl"> EOS</span>
<span class="w"> </span><span class="k">break</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">is_illegal</span>
<span class="w"> </span><span class="k">raise</span><span class="w"> </span><span class="s2">"Something illegal happend!"</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">cs</span><span class="o">.</span><span class="n">unshift</span><span class="p">(</span><span class="n">pre_c</span><span class="p">)</span>
<span class="w"> </span><span class="k">end</span>
<span class="w"> </span><span class="n">cs</span><span class="o">[</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">cs</span><span class="o">.</span><span class="n">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="o">].</span><span class="n">join</span>
<span class="k">end</span>
</pre></div></td></tr></table></div>
<p>のようになる.実際に</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">plain_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"This is a sample text to crypt by AES-CBC."</span>
<span class="n">attacked_cipher_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">encrypt_attack</span><span class="p">(</span><span class="n">plain_data</span><span class="p">)</span>
<span class="nb">p</span><span class="w"> </span><span class="n">attacked_cipher_data</span>
<span class="nb">p</span><span class="w"> </span><span class="n">decrypt</span><span class="p">(</span><span class="n">attacked_cipher_data</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>のように攻撃してみると,</p>
<pre class="literal-block">
Start detecting 3th block...
...................detected 15th byte!
C: "???????????????\xBD"
C': "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\xBF"
....................detected 14th byte!
C: "??????????????\xC0\xBD"
C': "\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\xC3\xBE"
...
..........detected 1th byte!
C: "?8\x80jG\xC0\xD8\xBF\x18[X@\xB1\xE7T\x93"
C': "\x11@\xF9\tw\xB9\xBB\x8Fik;1\xCC\x87(\xE6"
..................detected 0th byte!
C: "\xF48\x80jG\xC0\xD8\xBF\x18[X@\xB1\xE7T\x93"
C': "\xB1A\xF8\bv\xB8\xBA\x8Ehj:0\xCD\x86)\xE7"
"\xF48\x80jG\xC0\xD8\xBF\x18[X@\xB1\xE7T\x93\xC2[\xE2~\xC8\xAEO\x9Cf\x11}\x8F\xA5X\xC3\xED\xAE\eRI\x06Uk\x9E\xCB\x02n\xF9l\xC2E\x1A\xC8\xE8\x83\xBBc\x97\x82\x90R\xD5N]4\xFA\xC0\xBD"
"This is a sample text to crypt by AES-CBC."
</pre>
<p>のような出力が得られ,攻撃が成功してることが確認できる.</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,padding oracle attack の概要を見た.padding oracle を利用することで,暗号文からの平文の復元,改竄を行えることが分かった.ユーザに対して情報を提供することはユーザビリティの面では非常に重要だが,セキュリティの面では少しの情報で致命的な欠陥を招くこともある.そういうのは気をつけていかなきゃなと思いました(こなみ).</p>
<p>なお,以下の文献に非常にお世話になった:</p>
<ul class="simple">
<li><a class="reference external" href="http://rintaro.hateblo.jp/entry/2017/12/31/174327">Padding Oracle AttackによるCBC modeの暗号文解読と改ざん - security etc...</a></li>
<li><a class="reference external" href="http://inaz2.hatenablog.com/entry/2015/12/23/000923">CBC modeに対するPadding oracle attackをやってみる - ももいろテクノロジー</a></li>
</ul>
<table class="docutils footnote" frame="void" id="nist-block-cipher-modes" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td><a class="reference external" href="https://csrc.nist.gov/publications/detail/sp/800-38a/final">https://csrc.nist.gov/publications/detail/sp/800-38a/final</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="rfc-5652" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td><a class="reference external" href="http://tools.ietf.org/html/rfc5652#section-6.3">http://tools.ietf.org/html/rfc5652#section-6.3</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/07/padding-oracle-attack.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/07/padding-oracle-attack.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>BlockArguments で括弧を書かない生活を送る2020-07-05T12:12:00+09:002022-12-04T13:18:02+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-07-05:/blog/posts/2020/07/no-parenthesis-with-blockarguments/<p>GHC 8.6 から <tt class="docutils literal">BlockArguments</tt> という拡張が入った.これは構文拡張で,Haskell 2010 で必要だった幾つかの括弧を省略できるようにするもの …</p><p>GHC 8.6 から <tt class="docutils literal">BlockArguments</tt> という拡張が入った.これは構文拡張で,Haskell 2010 で必要だった幾つかの括弧を省略できるようにするものだ.この拡張を使うことで,Haskell プログラミングにおいて極限まで括弧を省略できるようになった.今回は,<tt class="docutils literal">BlockArguments</tt> の簡単な紹介と,どういう風に括弧の省略ができるかを見ていきたいと思う.</p>
<div class="section" id="auto-id-1">
<h2><tt class="docutils literal">BlockArguments</tt> 拡張<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Haskell 2010 では,構文要素として幾つかのブロック式が入っている.</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span>lexp → \ apat1 … apatn -> exp
| let decls in exp
| if exp [;] then exp [;] else exp
| case exp of { alts }
| do { stmts }
| fexp
</pre></div></td></tr></table></div>
<p>における,</p>
<dl class="docutils">
<dt>ラムダ式</dt>
<dd><tt class="docutils literal">\ apat1 … apatn <span class="pre">-></span> exp</tt></dd>
<dt><tt class="docutils literal">let</tt> 式</dt>
<dd><tt class="docutils literal">let decls in exp</tt></dd>
<dt><tt class="docutils literal">if</tt> 式</dt>
<dd><tt class="docutils literal">if exp [;] then exp [;] else exp</tt></dd>
<dt><tt class="docutils literal"><span class="pre">case-of</span></tt> 式</dt>
<dd><tt class="docutils literal">case exp of { alts }</tt></dd>
<dt><tt class="docutils literal">do</tt> 式</dt>
<dd><tt class="docutils literal">do { stmts }</tt></dd>
</dl>
<p>の5種類の式だ.他に,GHC 拡張で <tt class="docutils literal">mdo</tt>,<tt class="docutils literal">\case</tt>,<tt class="docutils literal">proc</tt> などもある.ところで,これらの式は <tt class="docutils literal">lexp</tt> に紐づいている.これは,中置記法構文において</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span>infixexp → lexp qop infixexp
| - infixexp
| lexp
</pre></div></td></tr></table></div>
<p>のように,左の式の構文要素として使用される.具体的には,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">atomically</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readTVar</span><span class="w"> </span><span class="n">tv</span>
<span class="w"> </span><span class="n">writeTVar</span><span class="w"> </span><span class="n">tv</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
</pre></div></td></tr></table></div>
<p>のように書ける.なお,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">\</span><span class="n">f</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="mi">0</span>
</pre></div></td></tr></table></div>
<p>のような式の場合,<tt class="docutils literal">(\f <span class="pre">-></span> f) $ 0</tt> か <tt class="docutils literal">\f <span class="pre">-></span> (f $ 0)</tt> の解釈の2通りが存在し,曖昧性が生じるが,これを解決するためのメタ規則が設定されており <a class="footnote-reference" href="#haskell2010-metarule" id="auto-id-2">[1]</a>,ブロック式は可能な限り,右に広くとることになっているため,この式は <tt class="docutils literal">\f <span class="pre">-></span> (f $ 0)</tt> に一意に解釈が決まる.よって,左にブロック式を書きたい場合は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">(</span><span class="nf">\</span><span class="n">f</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="mi">0</span>
</pre></div></td></tr></table></div>
<p>のように括弧で囲む必要がある.ところで,先ほどの</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">atomically</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readTVar</span><span class="w"> </span><span class="n">tv</span>
<span class="w"> </span><span class="n">writeTVar</span><span class="w"> </span><span class="n">tv</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
</pre></div></td></tr></table></div>
<p>の式は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">atomically</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readTVar</span><span class="w"> </span><span class="n">tv</span>
<span class="w"> </span><span class="n">writeTVar</span><span class="w"> </span><span class="n">tv</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
</pre></div></td></tr></table></div>
<p>のように,<tt class="docutils literal">$</tt> 無しで書くことはできない.関数適用の構文は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span>fexp → [fexp] aexp
aexp → qvar
| gcon
| literal
| ( exp )
| …
</pre></div></td></tr></table></div>
<p>のようになっている.<tt class="docutils literal">aexp</tt> の中で <tt class="docutils literal">lexp</tt> の構文を使用するには,括弧で囲む必要があるため,関数適用を <tt class="docutils literal">$</tt> 無しで書くには,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">atomically</span><span class="w"> </span><span class="p">(</span><span class="kr">do</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readTVar</span><span class="w"> </span><span class="n">tv</span>
<span class="w"> </span><span class="n">writeTVar</span><span class="w"> </span><span class="n">tv</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="p">)</span>
</pre></div></td></tr></table></div>
<p>のように括弧で囲む必要がある.<tt class="docutils literal">BlockArguments</tt> の概要は,ブロック式を <tt class="docutils literal">lexp</tt> から <tt class="docutils literal">aexp</tt> に移すことで,関数適用時にも括弧無しで書けるようにするというものだ.結果,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">atomically</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readTVar</span><span class="w"> </span><span class="n">tv</span>
<span class="w"> </span><span class="n">writeTVar</span><span class="w"> </span><span class="n">tv</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
</pre></div></td></tr></table></div>
<p>という式が,有効になる.これが,<tt class="docutils literal">BlockArguments</tt> 拡張になる.</p>
</div>
<div class="section" id="do">
<h2><tt class="docutils literal">do</tt> によるレイアウトハッキング<a class="headerlink" href="#do" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,<tt class="docutils literal">BlockArguments</tt> はここまで見ると単純な拡張に見える.ところが,これを <tt class="docutils literal">do</tt> 構文と組み合わせると,今までの <tt class="docutils literal">$</tt> による書き方を書きやすくするのに加え,それより遥かに豊かな表記法を提供してくれる.例えば,以下のような書き方が可能になる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">foldl'</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="nf">\</span><span class="n">acc</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">shows</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="n">replicate</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="s">""</span>
</pre></div></td></tr></table></div>
<p>この式は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">foldl'</span>
<span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">acc</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">shows</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="n">replicate</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="s">""</span>
</pre></div></td></tr></table></div>
<p>と同等になる.そのカラクリは,<tt class="docutils literal">do</tt> 式の脱糖方法にある.<tt class="docutils literal">do</tt> 式は,構成要素が1つの式しか無い場合,何も行わずその式を展開する.<tt class="docutils literal">do</tt> 式の脱糖が意味を持つのは2つ以上式が並んだ場合のみだ.それを利用すれば,モナドと何の関係性もない式を,<tt class="docutils literal">do</tt> で使うことにより,ある式の範囲を明示することができる.</p>
<p><tt class="docutils literal">$</tt> は演算子の優先順位により,両側の式範囲を示すマーカーとなるが,<tt class="docutils literal">do</tt> は代わりにレイアウトルールによりその範囲を明示するのに使用できる.ただ,この違いは注意が必要でもある.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>という式は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">h</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>と同等の式になる.ところが,<tt class="docutils literal">$</tt> を何も考えずに</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>というように,<tt class="docutils literal">do</tt> に置き換えるだけでは,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="p">(</span><span class="n">h</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>というように,元の式とは異なる式になってしまう.このような場合は,<tt class="docutils literal">$</tt> を置き換えることはできない.また,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">id</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Identity</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">runIdentity</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>というような式を <tt class="docutils literal">do</tt> で書く場合,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">id</span><span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="kt">Identity</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">runIdentity</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>と書いてしまうと,パースエラーになる.<tt class="docutils literal">do</tt> 式は <tt class="docutils literal">{</tt> を省略した場合はレイアウトルールにより解釈が行われる.上の式は,<tt class="docutils literal">runIdentity</tt> の前の <tt class="docutils literal">{</tt> が <tt class="docutils literal">do</tt> の現在の位置より前にあるため,その位置でレイアウトが閉じてしまい,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">id</span><span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">Identity</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">runIdentity</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>のように解釈されることになってしまう.よって,この場合は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">id</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kt">Identity</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">runIdentity</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>のように,一続きになる式をインデントを意識して書く必要がある.<tt class="docutils literal">runIdentity</tt> の前の <tt class="docutils literal">{</tt> は,<tt class="docutils literal">do</tt> の位置より深くする,つまり <tt class="docutils literal">Identity</tt> を書いた位置より深いところで書く必要がある.ただ,これは使いようによっては,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">foldl'</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="nf">\</span><span class="n">acc</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">-></span>
<span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">shows</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="n">replicate</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="s">""</span>
</pre></div></td></tr></table></div>
<p>のように複数行のブロックの範囲を明示することもできる.</p>
<p>これを使えば,例えば <tt class="docutils literal"><span class="pre">optparse-applicative</span></tt> などの applicative style を多用するライブラリで,以下のように括弧をなくすことができる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">sample</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Sample</span>
<span class="w"> </span><span class="o"><$></span><span class="w"> </span><span class="n">strOption</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">long</span><span class="w"> </span><span class="s">"hello"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">metavar</span><span class="w"> </span><span class="s">"TARGET"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="s">"Target for the greeting"</span>
<span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">switch</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">long</span><span class="w"> </span><span class="s">"quiet"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">short</span><span class="w"> </span><span class="sc">'q'</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="s">"Whether to be quiet"</span>
<span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">auto</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">long</span><span class="w"> </span><span class="s">"enthusiasm"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="s">"How enthusiastically to greet"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">showDefault</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">metavar</span><span class="w"> </span><span class="s">"INT"</span>
</pre></div></td></tr></table></div>
<p>これは,演算子の優先順位の関係で <tt class="docutils literal">$</tt> を使っての括弧の省略はできないため,通常は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">sample</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Sample</span>
<span class="w"> </span><span class="o"><$></span><span class="w"> </span><span class="n">strOption</span>
<span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="n">long</span><span class="w"> </span><span class="s">"hello"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">metavar</span><span class="w"> </span><span class="s">"TARGET"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="s">"Target for the greeting"</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">switch</span>
<span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="n">long</span><span class="w"> </span><span class="s">"quiet"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">short</span><span class="w"> </span><span class="sc">'q'</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="s">"Whether to be quiet"</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="n">auto</span>
<span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="n">long</span><span class="w"> </span><span class="s">"enthusiasm"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">help</span><span class="w"> </span><span class="s">"How enthusiastically to greet"</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">showDefault</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">metavar</span><span class="w"> </span><span class="s">"INT"</span>
<span class="w"> </span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>のように括弧をつける必要があった.それを,<tt class="docutils literal">BlockArguments</tt> による <tt class="docutils literal">do</tt> 構文を使用することで,<tt class="docutils literal">$</tt> より多彩な表現ができるようになる.また,前に紹介した</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>も実は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">do</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">h</span>
<span class="nf">x</span>
</pre></div></td></tr></table></div>
<p>というように書き方を工夫すれば,括弧や <tt class="docutils literal">$</tt> を省略できる.ただ,やりすぎは可読性を著しく落とすので,用量用法を守って使用すると良いと思う.</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今回は,<tt class="docutils literal">BlockArguments</tt> の紹介と,その拡張下での <tt class="docutils literal">do</tt> 構文とレイアウトルールによる,括弧や <tt class="docutils literal">$</tt> の省略法を紹介した.実は最近この方法を使っていて,完全に <tt class="docutils literal">$</tt> を使わなくても大体書けるなあって感じになった.</p>
<p>基本的には,ある式の範囲を明示したい時は,</p>
<ul class="simple">
<li><tt class="docutils literal">do</tt> から始めて,複数行に渡る場合は最初のインデントより以降の行のインデントを深くする</li>
<li>その式の範囲が終わったら,改行して今までのインデントより浅いところから始める</li>
</ul>
<p>ということをすれば,括弧無しでレイアウトルールに任せた式表記ができる.用量用法を守って使っていきたい.こちらからは以上です.</p>
<table class="docutils footnote" frame="void" id="haskell2010-metarule" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><a class="reference external" href="https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-220003">https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-220003</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/07/no-parenthesis-with-blockarguments.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/07/no-parenthesis-with-blockarguments.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>XCode でビルドするときに引っかかったところ2020-06-18T12:58:47+09:002020-07-06T13:29:16+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-06-18:/blog/posts/2020/06/xcode-trouble-shooting/<p>XCode を使ってる時,ちょっと検索しにくい問題に2件当たったので,備忘録として残しておく.</p>
<div class="section" id="undefined-symbols-for-architecture-i386">
<h2>Undefined symbols for architecture i386<a class="headerlink" href="#undefined-symbols-for-architecture-i386" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>iOS 用の Objective-C のプロジェクトをビ …</p></div><p>XCode を使ってる時,ちょっと検索しにくい問題に2件当たったので,備忘録として残しておく.</p>
<div class="section" id="undefined-symbols-for-architecture-i386">
<h2>Undefined symbols for architecture i386<a class="headerlink" href="#undefined-symbols-for-architecture-i386" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>iOS 用の Objective-C のプロジェクトをビルドしてる際,なぜかリンクに失敗し,ある特定の framework について,</p>
<pre class="literal-block">
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_XXX", referenced from:
objc-class-ref in XXX.o
</pre>
<p>というエラーが全てのシンボルについて出ていた.で,このリンカエラーが起こる前に,次のようなメッセージが出ていた:</p>
<pre class="literal-block">
Ignoring file XXX.framework/XXX, missing required architecture i386 in file XXX.framework/XXX
</pre>
<p>僕は,iOS プログラミングはほぼ初体験だったので,そもそも framework というのがどういうものなのか知らなかったんだけど,こいつはライブラリアーカイブやヘッダ情報などが詰め込まれているものらしい.ライブラリはアーキテクチャごとに用意されていて,どうやら今回の場合,この framework に i386 アーキテクチャが入っていないということらしい.</p>
<p>ところで,件の framework は他のプロジェクトを自分でビルドして持ってきたものだった.自分でビルドしたものに必要なアーキテクチャ用のライブラリアーカイブが入っていないのは不思議だ.で,いろいろ調べてみると,どうやら今回は次のような原因によるものだった (と思われる):</p>
<ul class="simple">
<li>Debug ビルドでは,XCode はデフォルトで必要なアーキテクチャ用のライブラリしか作らない</li>
<li>対象としてる iOS のバージョンが違った</li>
</ul>
<p>一つ目は,どうやらいろんな人が詰まる問題みたいで,"Build Settings" の "Build Active Architecture Only" という設定が問題になる.この設定は,幾つかの標準アーキテクチャ用のライブラリしかビルドしないという設定で,デフォルトで Debug ビルド時は YES,Release ビルド時は NO になっている.今回はもう一つのプロジェクトの方を Debug ビルドしていて,そのプロジェクトの設定はデフォルトのままだったので,標準アーキテクチャしか framework に入っていなかった.なお,framework がどのアーキテクチャ向けのものなのかは,</p>
<pre class="literal-block">
$ xcrun lipo -info XXX.framework/XXX
Architectures in the fat file: XXX are: armv7 armv7s i386 arm64
</pre>
<p>で確認できる.世の中で配布されている framework は結構アーキテクチャに抜けがあったりするっぽいので,<tt class="docutils literal">missing required architecture</tt> と言われた場合は,まずは上のコマンドで対応してるアーキテクチャを確認してみると良いと思う.</p>
<p>さて,今回は両方 Debug ビルドしていたので,両方標準アーキテクチャが同じなら実は Release ビルドしない限り問題は起きなかったはずだ.では,なんで怒られたかなんだけど,実はいまいち原因が分かっていない.おそらく対象の iOS バージョンが違ったのが原因で,標準アーキテクチャが変わったんじゃないかと思うんだけど,実は詳しく調べてないので細かい原因は判明してない.</p>
<p>とりあえずめんどかったので,今回は framework を作るプロジェクトの方の,Debug ビルド時の設定で,"Build Active Architecture Only" を YES から NO に変更し,一通りのアーキテクチャに対応させることにした.基本的な対応は Release ビルドを行うことだと思う.ただ今回は Debug ビルド時のロジックなども欲しかったのでそういった対応をした感じ.</p>
</div>
<div class="section" id="extra-info-about-plist-acl-not-found">
<h2>Extra info about plist: ACL=<not found><a class="headerlink" href="#extra-info-about-plist-acl-not-found" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,上の設定でビルドをしてアプリをシミュレータで起動させてみると,今度は次のようなエラーが表示された:</p>
<pre class="literal-block">
This app could not be installed at this time.
Could not install at this time.
Failed to load Info.plist from bundle at path ~/Library/Developer/CoreSimulator/Devices/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX/data/Library/Caches/com.apple.mobile.installd.staging/temp.A3gmX5/extracted/Test.app/Frameworks/XXX.framework; Extra info about plist: ACL=<not found>
</pre>
<p>このエラーは Run 時に,アラートダイアログで通知されて,<tt class="docutils literal">Details</tt> / <tt class="docutils literal">OK</tt> というボタンが表示される.とりあえず,<tt class="docutils literal">Details</tt> の方を押してみると,次のようなことを言われる:</p>
<pre class="literal-block">
Domain: MIInstallerErrorDomain
Code: 35
User Info: {
FunctionName = "-[MIBundle _validateWithError:]";
LegacyErrorString = PackageInspectionFailed;
SourceFileLine = 128;
}
</pre>
<p>これでは何も分からないが,どうやら先ほどのもう一つのプロジェクトでビルドした framework の <tt class="docutils literal">Info.plist</tt> がおかしそうな印象を受ける.ただ,実はこの framework は他のアプリに組み込んで動かしてみたことがあって,その時はこういうことは無かった.</p>
<p>で,何が悪かったのかだけど,この framework を追加する際の設定が悪かった.framework をプロジェクトに追加する際,その埋め込み方が設定できる.今回は,これが <tt class="docutils literal">Embed & Sign</tt> になっていた.これも詳しい原因はちょっと調べてないんだけど,Debug ビルドで作った signing とか何もされてないやつを,embed しようとすると上のようなエラーになるんかな?</p>
<p>今回は特に embed とかする必要ないし,単にシミュレータで動作確認したかっただけなんで,<tt class="docutils literal">Do Not Embed</tt> にすると無事起動するようになった.</p>
</div>
<div class="section" id="auto-id-1">
<h2>まとめ<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>単にビルドして動かしたかっただけなのに,この2つの問題解決するだけで結構時間かかっちゃった.後,Objective-C 何も分からん.今回は以上です.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/06/xcode-trouble-shooting.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/06/xcode-trouble-shooting.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>gRPC クライアントをAndroid アプリで書く2020-04-19T12:41:04+09:002020-04-19T12:41:04+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-04-19:/blog/posts/2020/04/kotlin-android-grpc/<p>単純に gRPC クライアントを Android アプリで書いて,mock サーバを Kotlin で書くだけなのにすごく苦労したので,備忘録的に書いと …</p><p>単純に gRPC クライアントを Android アプリで書いて,mock サーバを Kotlin で書くだけなのにすごく苦労したので,備忘録的に書いとく.なお,最終的に出来上がったものは,<a class="reference external" href="https://github.com/mizunashi-mana/grpc-android-example">https://github.com/mizunashi-mana/grpc-android-example</a> に上げてある.</p>
<div class="section" id="android-gradle">
<h2>Android の Gradle プロジェクトの基本<a class="headerlink" href="#android-gradle" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まず,Android Studio で新規プロジェクトを作る.基本はここから大きく変更しなくて良い.Gradle のバージョンが古かったりするが,それは android 向けの gradle プラグインが最新に対応していないから.具体的な対応状況は,<a class="reference external" href="https://developer.android.com/studio/releases/gradle-plugin?hl=ja#updating-gradle">https://developer.android.com/studio/releases/gradle-plugin?hl=ja#updating-gradle</a> に書いてある.現状の作成段階では,</p>
<ul class="simple">
<li>android gradle plugin: 3.6.3</li>
<li>対応してる gradle の最新: 5.6.4</li>
</ul>
<p>みたいな感じだった.で,Android Studio が生成する <tt class="docutils literal">build.gradle</tt> は使う gradle のバージョンが明示されていないので,書いとくといい <a class="footnote-reference" href="#notice-gradle-wrapper" id="auto-id-1">[1]</a>:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">wrapper</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">gradleVersion</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'5.6.4'</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p>なお,このバージョンでうまく動く JDK のバージョンは限られていて,基本 JDK 8 を使うのが安定.<tt class="docutils literal">direnv</tt> とかで <tt class="docutils literal">JAVA_HOME</tt> を JDK 8 のものにしとくと良い.</p>
<p>Android の Gradle 構成は,ルートにある <tt class="docutils literal">build.gradle</tt> がプロジェクト全体のもの,<tt class="docutils literal">app/build.gradle</tt> が Android アプリモジュール用と言うようになっている.プロジェクト全体で共通の設定はルートの <tt class="docutils literal">build.gradle</tt> に,モジュール専用のものは <tt class="docutils literal">app/build.gradle</tt> に書いとくと良い.</p>
</div>
<div class="section" id="grpc-kotlin">
<h2>gRPC のモックサーバを Kotlin で書く<a class="headerlink" href="#grpc-kotlin" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まずはモックサーバの方を足してく.まずは全体設定から.共通で使うバージョン情報などを,ルートの <tt class="docutils literal">build.gradle</tt> に埋め込む:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">buildscript</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">ext</span><span class="o">.</span><span class="na">kotlin_version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'1.3.61'</span>
<span class="w"> </span><span class="n">ext</span><span class="o">.</span><span class="na">coroutines_version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'1.3.3'</span>
<span class="w"> </span><span class="n">ext</span><span class="o">.</span><span class="na">protobuf_version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'3.11.1'</span>
<span class="w"> </span><span class="n">ext</span><span class="o">.</span><span class="na">grpc_version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'1.28.1'</span>
<span class="w"> </span><span class="n">ext</span><span class="o">.</span><span class="na">grpc_kotlin_version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'0.1.1'</span>
<span class="w"> </span><span class="o">...</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p>Kotlin 用の gRPC ライブラリ,<tt class="docutils literal"><span class="pre">grpc-kotlin</span></tt> は,coroutine flow を使っていい感じに streaming rpc の処理を書けるようになってるので,その為に coroutine api のバージョン情報を足している.後は使用する</p>
<ul class="simple">
<li><tt class="docutils literal">protobuf</tt> のバージョン</li>
<li><tt class="docutils literal"><span class="pre">grpc-java</span></tt> のバージョン</li>
<li><tt class="docutils literal"><span class="pre">grpc-kotlin</span></tt> のバージョン</li>
</ul>
<p>を指定している.これらは,モックサーバと Android アプリで共通のバージョンを使う.後は,<tt class="docutils literal">proto</tt> ファイルをサーバとアプリ共通で使う為,ルートに <tt class="docutils literal">proto</tt> ディレクトリを作りその中に置くようにする.そして,そのパスも共通設定に入れておく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">buildscript</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="n">ext</span><span class="o">.</span><span class="na">proto_dir</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">file</span><span class="o">(</span><span class="s1">'proto'</span><span class="o">)</span>
<span class="w"> </span><span class="o">...</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p>後,<tt class="docutils literal">protobuf</tt> の gradle プラグインを使う為,classpath を追加しておく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">buildscript</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="n">classpath</span><span class="w"> </span><span class="s1">'com.google.protobuf:protobuf-gradle-plugin:0.8.12'</span>
<span class="w"> </span><span class="o">}</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p>次に,モックサーバ用に gradle のモジュールをさらに生やす.やることとしては,</p>
<ol class="arabic simple">
<li><tt class="docutils literal">mock</tt> ディレクトリを作る</li>
<li><tt class="docutils literal">mock/build.gradle</tt> を書く</li>
<li><tt class="docutils literal"><span class="pre">mock/.gitignore</span></tt> を書く</li>
<li><tt class="docutils literal">mock</tt> モジュールのメインクラスを作る</li>
</ol>
<p>みたいな感じ.<tt class="docutils literal">build.gradle</tt> は,まず必要なプラグインを書いていく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">apply</span><span class="w"> </span><span class="nl">plugin:</span><span class="w"> </span><span class="s1">'application'</span>
<span class="n">apply</span><span class="w"> </span><span class="nl">plugin:</span><span class="w"> </span><span class="s1">'kotlin'</span>
<span class="n">apply</span><span class="w"> </span><span class="nl">plugin:</span><span class="w"> </span><span class="s1">'idea'</span>
<span class="n">apply</span><span class="w"> </span><span class="nl">plugin:</span><span class="w"> </span><span class="s1">'com.google.protobuf'</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">application</tt> プラグインは,<tt class="docutils literal">run</tt> とか生やしたり,配布用の実行ファイルアーカイブ作ってくれたりするやつ.<tt class="docutils literal">kotlin</tt> と <tt class="docutils literal">com.google.protobuf</tt> は名前の通り.<tt class="docutils literal">idea</tt> プラグインは最初何のために必要なのか分かってなかったんだけど,こいつがないと <tt class="docutils literal">protobuf</tt> プラグインが生成した kotlin ファイルを何故か gradle が認識してくれない.一応表面上は JetBrains 製エディタと連携するためのプラグインということになっているが,とりあえずこいつ入れないと <tt class="docutils literal"><span class="pre">grpc-kotlin</span></tt> が機能しないので入れてる.意味不明なので,誰か原因と解決方法知ってる人いたら教えてくれって感じ.</p>
<p>後は,メインクラスの指定と <tt class="docutils literal">proto</tt> ディレクトリの指定をやっていく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">mainClassName</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'com.example.myapplication.mock.MainKt'</span>
<span class="n">sourceSets</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">main</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">proto</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">srcDir</span><span class="w"> </span><span class="n">proto_dir</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p>メインクラスは,オブジェクト名 + Kt にする.それから,依存ライブラリを指定していく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">compileOnly</span><span class="w"> </span><span class="s1">'javax.annotation:javax.annotation-api:1.2'</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"io.grpc:grpc-kotlin-stub:${grpc_kotlin_version}"</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s1">'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.61'</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"org.jetbrains.kotlinx:kotlinx-coroutines-core:${coroutines_version}"</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"com.google.protobuf:protobuf-java:${protobuf_version}"</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"com.google.protobuf:protobuf-java-util:${protobuf_version}"</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"io.grpc:grpc-netty-shaded:${grpc_version}"</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"io.grpc:grpc-protobuf:${grpc_version}"</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"io.grpc:grpc-stub:${grpc_version}"</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal"><span class="pre">javax.annotation-api</span></tt> とその他の <tt class="docutils literal">grpc</tt> 関連のは <tt class="docutils literal">proto</tt> から生成される Kotlin ファイルに必要.後は,まあ必要なもの一式って感じ.それから,<tt class="docutils literal">protobuf</tt> の出力設定を書く:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">protobuf</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">protoc</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">artifact</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"com.google.protobuf:protoc:${protobuf_version}"</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="n">plugins</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">grpc</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">artifact</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"io.grpc:protoc-gen-grpc-java:${grpc_version}"</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="n">grpckt</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">artifact</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"io.grpc:protoc-gen-grpc-kotlin:${grpc_kotlin_version}"</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="n">generateProtoTasks</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">all</span><span class="o">().</span><span class="na">each</span><span class="w"> </span><span class="o">{</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">task</span><span class="o">.</span><span class="na">plugins</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">grpc</span><span class="w"> </span><span class="o">{</span><span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="n">grpckt</span><span class="w"> </span><span class="o">{</span><span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal"><span class="pre">grpc-kotlin</span></tt> の出力ファイルは,基本 <tt class="docutils literal"><span class="pre">grpc-java</span></tt> の生成ファイルを元にしているっぽいので,どっちの出力オプションも加えておく.これで,<tt class="docutils literal">proto</tt> ファイルからいい感じの Kotlin ファイルが出来上がるようになる.</p>
<p><tt class="docutils literal"><span class="pre">mock/.gitignore</span></tt> は,<tt class="docutils literal">/build</tt> だけ書いとけばおk.</p>
<p>後は,<tt class="docutils literal">mock</tt> モジュールのメインクラスを作っておく.とりあえず,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">package</span><span class="w"> </span><span class="nn">com.example.myapplication.mock</span>
<span class="kd">fun</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"Hello, World!"</span><span class="p">)</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>と書いて動作確認して見る:</p>
<pre class="literal-block">
$ ./gradlew mock:run
...
Hello, World!
</pre>
<p>次に,<tt class="docutils literal">proto</tt> ファイルを作る.<tt class="docutils literal">proto/hello.proto</tt> に,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">syntax</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"proto3"</span><span class="p">;</span>
<span class="k">package</span><span class="w"> </span><span class="nn">com.example.myapplication.proto;</span>
<span class="n">service</span><span class="w"> </span><span class="n">Service</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">rpc</span><span class="w"> </span><span class="n">Connect</span><span class="w"> </span><span class="p">(</span><span class="n">stream</span><span class="w"> </span><span class="n">Post</span><span class="p">)</span><span class="w"> </span><span class="n">returns</span><span class="w"> </span><span class="p">(</span><span class="n">stream</span><span class="w"> </span><span class="n">Post</span><span class="p">)</span><span class="w"> </span><span class="p">{}</span>
<span class="p">}</span>
<span class="n">message</span><span class="w"> </span><span class="n">Post</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="n">message</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>という感じで,双方向にメッセージを垂れ流すインターフェースを定義しておく.なお,オプションで出力する Java 用のパッケージ名などはいい感じに <a class="reference external" href="https://developers.google.com/protocol-buffers/docs/proto3#options">制御できる</a>.今回は,両方 Kotlin で特にサーバとクライアントでパッケージ名別にする必要とかないので,<tt class="docutils literal">package</tt> 部分をそのまま使ってもらう.後は,モックサーバ本体を書く.さっきのメインクラスを</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span>
<span class="normal">62</span>
<span class="normal">63</span>
<span class="normal">64</span>
<span class="normal">65</span>
<span class="normal">66</span>
<span class="normal">67</span>
<span class="normal">68</span>
<span class="normal">69</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">/*</span>
<span class="cm"> * Copyright 2020 gRPC authors.</span>
<span class="cm"> *</span>
<span class="cm"> * Licensed under the Apache License, Version 2.0 (the "License");</span>
<span class="cm"> * you may not use this file except in compliance with the License.</span>
<span class="cm"> * You may obtain a copy of the License at</span>
<span class="cm"> *</span>
<span class="cm"> * http://www.apache.org/licenses/LICENSE-2.0</span>
<span class="cm"> *</span>
<span class="cm"> * Unless required by applicable law or agreed to in writing, software</span>
<span class="cm"> * distributed under the License is distributed on an "AS IS" BASIS,</span>
<span class="cm"> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span>
<span class="cm"> * See the License for the specific language governing permissions and</span>
<span class="cm"> * limitations under the License.</span>
<span class="cm"> */</span>
<span class="k">package</span><span class="w"> </span><span class="nn">com.example.myapplication.mock</span>
<span class="k">import</span><span class="w"> </span><span class="nn">com.example.myapplication.proto.Hello</span>
<span class="k">import</span><span class="w"> </span><span class="nn">com.example.myapplication.proto.ServiceGrpcKt</span>
<span class="k">import</span><span class="w"> </span><span class="nn">io.grpc.Server</span>
<span class="k">import</span><span class="w"> </span><span class="nn">io.grpc.ServerBuilder</span>
<span class="k">import</span><span class="w"> </span><span class="nn">kotlinx.coroutines.flow.Flow</span>
<span class="k">import</span><span class="w"> </span><span class="nn">kotlinx.coroutines.flow.collect</span>
<span class="k">import</span><span class="w"> </span><span class="nn">kotlinx.coroutines.flow.flow</span>
<span class="kd">class</span><span class="w"> </span><span class="nc">HelloServer</span><span class="w"> </span><span class="k">constructor</span><span class="p">(</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">port</span><span class="p">:</span><span class="w"> </span><span class="kt">Int</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">server</span><span class="p">:</span><span class="w"> </span><span class="n">Server</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ServerBuilder</span>
<span class="w"> </span><span class="p">.</span><span class="na">forPort</span><span class="p">(</span><span class="n">port</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">addService</span><span class="p">(</span><span class="n">HelloService</span><span class="p">())</span>
<span class="w"> </span><span class="p">.</span><span class="na">build</span><span class="p">()</span>
<span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">start</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">server</span><span class="p">.</span><span class="na">start</span><span class="p">()</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"Server started, listening on </span><span class="si">$</span><span class="n">port</span><span class="s">"</span><span class="p">)</span>
<span class="w"> </span><span class="n">Runtime</span><span class="p">.</span><span class="na">getRuntime</span><span class="p">().</span><span class="na">addShutdownHook</span><span class="p">(</span>
<span class="w"> </span><span class="n">Thread</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"*** shutting down gRPC server since JVM is shutting down"</span><span class="p">)</span>
<span class="w"> </span><span class="k">this</span><span class="nd">@HelloServer.stop</span><span class="p">()</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="s">"*** server shut down"</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">stop</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">server</span><span class="p">.</span><span class="na">shutdown</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">blockUntilShutdown</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">server</span><span class="p">.</span><span class="na">awaitTermination</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">HelloService</span><span class="p">:</span><span class="w"> </span><span class="n">ServiceGrpcKt</span><span class="p">.</span><span class="na">ServiceCoroutineImplBase</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">connect</span><span class="p">(</span><span class="n">requests</span><span class="p">:</span><span class="w"> </span><span class="n">Flow</span><span class="o"><</span><span class="n">Hello</span><span class="p">.</span><span class="na">Post</span><span class="o">></span><span class="p">):</span><span class="w"> </span><span class="n">Flow</span><span class="o"><</span><span class="n">Hello</span><span class="p">.</span><span class="na">Post</span><span class="o">></span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">flow</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">requests</span><span class="p">.</span><span class="na">collect</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">request</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">emit</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="kd">fun</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">port</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">5000</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">server</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HelloServer</span><span class="p">(</span><span class="n">port</span><span class="p">)</span>
<span class="w"> </span><span class="n">server</span><span class="p">.</span><span class="na">start</span><span class="p">()</span>
<span class="w"> </span><span class="n">server</span><span class="p">.</span><span class="na">blockUntilShutdown</span><span class="p">()</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><a class="reference external" href="https://github.com/grpc/grpc-kotlin/tree/v0.1.1/examples">公式のサンプル</a> ちょっと書き換えただけのやつ.これを走らせると,</p>
<pre class="literal-block">
$ ./gradlew mock:run
...
Server started, listening on 5000
</pre>
<p>って感じで待機して,5000 番に gRPC サーバが立つ.こいつ自体は単なるエコーサーバで,送ってきたやつそのまま送り返すだけ.</p>
</div>
<div class="section" id="android-grpc">
<h2>Android アプリで gRPC クライアントを作る<a class="headerlink" href="#android-grpc" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Android アプリ側も同じく,<tt class="docutils literal">build.gradle</tt> を調整する.まず <tt class="docutils literal">protobuf</tt> プラグインを足す:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">apply</span><span class="w"> </span><span class="nl">plugin:</span><span class="w"> </span><span class="s1">'com.google.protobuf'</span>
</pre></div></td></tr></table></div>
<p>それから,<tt class="docutils literal">proto</tt> ディレクトリを設定する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">android</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="n">sourceSets</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">main</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">proto</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">srcDir</span><span class="w"> </span><span class="n">proto_dir</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">...</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p>後は,依存ライブラリを足す:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="n">compileOnly</span><span class="w"> </span><span class="s1">'javax.annotation:javax.annotation-api:1.2'</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"io.grpc:grpc-okhttp:${grpc_version}"</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"io.grpc:grpc-protobuf-lite:${grpc_version}"</span>
<span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s2">"io.grpc:grpc-stub:${grpc_version}"</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p>Android 側は <tt class="docutils literal"><span class="pre">protobuf-lite</span></tt> というのを使う.これは軽量版になってて,通常の JVM に吐き出すよりいい感じに Android 用に最適化してコードサイズ減らしたクラスを生成してくれるらしい.で,それ用に <tt class="docutils literal">protobuf</tt> の設定も調整する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">protobuf</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">protoc</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">artifact</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"com.google.protobuf:protoc:${protobuf_version}"</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="n">plugins</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">grpc</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">artifact</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"io.grpc:protoc-gen-grpc-java:${grpc_version}"</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="n">generateProtoTasks</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">all</span><span class="o">().</span><span class="na">each</span><span class="w"> </span><span class="o">{</span><span class="w"> </span><span class="n">task</span><span class="w"> </span><span class="o">-></span>
<span class="w"> </span><span class="n">task</span><span class="o">.</span><span class="na">builtins</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">java</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="s1">'lite'</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="n">task</span><span class="o">.</span><span class="na">plugins</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">grpc</span><span class="w"> </span><span class="o">{</span>
<span class="w"> </span><span class="n">option</span><span class="w"> </span><span class="s1">'lite'</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="w"> </span><span class="o">}</span>
<span class="o">}</span>
</pre></div></td></tr></table></div>
<p>それから,Android のマニフェストでネットワーク通信の権限が得られるようにしておく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="cp"><?xml version="1.0" encoding="utf-8"?></span>
<span class="nt"><manifest</span><span class="w"> </span><span class="na">xmlns:android=</span><span class="s">"http://schemas.android.com/apk/res/android"</span>
<span class="w"> </span><span class="err">...</span><span class="nt">></span>
<span class="w"> </span><span class="nt"><uses-permission</span><span class="w"> </span><span class="na">android:name=</span><span class="s">"android.permission.INTERNET"</span><span class="w"> </span><span class="nt">/></span>
<span class="w"> </span>...
<span class="nt"></manifest></span>
</pre></div></td></tr></table></div>
<p>これがないと,<tt class="docutils literal">socket failed: EPERM (Operation not permitted)</tt> と言われてクライアントが立ち上がらない.後は,適当にクライアント書くだけ.アプリのデザインは最初にあげたリポジトリみれくれって感じ.メインアクティビティのコードだけ載せとく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span>
<span class="normal">62</span>
<span class="normal">63</span>
<span class="normal">64</span>
<span class="normal">65</span>
<span class="normal">66</span>
<span class="normal">67</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">package</span><span class="w"> </span><span class="nn">com.example.myapplication</span>
<span class="k">import</span><span class="w"> </span><span class="nn">android.os.Bundle</span>
<span class="k">import</span><span class="w"> </span><span class="nn">android.os.Handler</span>
<span class="k">import</span><span class="w"> </span><span class="nn">android.util.Log</span>
<span class="k">import</span><span class="w"> </span><span class="nn">androidx.appcompat.app.AppCompatActivity</span>
<span class="k">import</span><span class="w"> </span><span class="nn">androidx.databinding.DataBindingUtil</span>
<span class="k">import</span><span class="w"> </span><span class="nn">com.example.myapplication.proto.Hello</span>
<span class="k">import</span><span class="w"> </span><span class="nn">com.example.myapplication.proto.ServiceGrpc</span>
<span class="k">import</span><span class="w"> </span><span class="nn">io.grpc.ManagedChannelBuilder</span>
<span class="k">import</span><span class="w"> </span><span class="nn">io.grpc.stub.StreamObserver</span>
<span class="k">import</span><span class="w"> </span><span class="nn">com.example.myapplication.databinding.ActivityMainBinding</span>
<span class="kd">class</span><span class="w"> </span><span class="nc">MainActivity</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">AppCompatActivity</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">lateinit</span><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nv">handler</span><span class="p">:</span><span class="w"> </span><span class="n">Handler</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">lateinit</span><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nv">stream</span><span class="p">:</span><span class="w"> </span><span class="n">StreamObserver</span><span class="o"><</span><span class="n">Hello</span><span class="p">.</span><span class="na">Post</span><span class="o">></span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">lateinit</span><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nv">binding</span><span class="p">:</span><span class="w"> </span><span class="n">ActivityMainBinding</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nv">i</span><span class="p">:</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">0</span>
<span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span><span class="w"> </span><span class="n">Bundle?)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">super</span><span class="p">.</span><span class="na">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span>
<span class="w"> </span><span class="n">handler</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Handler</span><span class="p">()</span>
<span class="w"> </span><span class="n">binding</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DataBindingUtil</span><span class="p">.</span><span class="na">setContentView</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="p">.</span><span class="na">layout</span><span class="p">.</span><span class="na">activity_main</span><span class="p">)</span>
<span class="w"> </span><span class="n">stream</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">startgRPCClient</span><span class="p">(</span><span class="n">handler</span><span class="p">,</span><span class="w"> </span><span class="n">binding</span><span class="p">)</span>
<span class="w"> </span><span class="n">binding</span><span class="p">.</span><span class="na">button</span><span class="p">.</span><span class="na">setOnClickListener</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">stream</span><span class="p">.</span><span class="na">onNext</span><span class="p">(</span>
<span class="w"> </span><span class="n">Hello</span><span class="p">.</span><span class="na">Post</span><span class="p">.</span><span class="na">newBuilder</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="na">setMessage</span><span class="p">(</span><span class="s">"button clicked: </span><span class="si">$</span><span class="n">i</span><span class="s">"</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">build</span><span class="p">()</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="n">i</span><span class="o">++</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">companion</span><span class="w"> </span><span class="kd">object</span><span class="w"> </span><span class="err">{</span>
<span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">startgRPCClient</span><span class="p">(</span>
<span class="w"> </span><span class="n">mainHandler</span><span class="p">:</span><span class="w"> </span><span class="n">Handler</span><span class="p">,</span>
<span class="w"> </span><span class="n">binding</span><span class="p">:</span><span class="w"> </span><span class="n">ActivityMainBinding</span>
<span class="w"> </span><span class="p">):</span><span class="w"> </span><span class="n">StreamObserver</span><span class="o"><</span><span class="n">Hello</span><span class="p">.</span><span class="na">Post</span><span class="o">></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">channel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ManagedChannelBuilder</span>
<span class="w"> </span><span class="p">.</span><span class="na">forAddress</span><span class="p">(</span><span class="s">"10.0.2.2"</span><span class="p">,</span><span class="w"> </span><span class="m">5000</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="na">usePlaintext</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="na">build</span><span class="p">()</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">stub</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ServiceGrpc</span><span class="p">.</span><span class="na">newStub</span><span class="p">(</span><span class="n">channel</span><span class="p">)</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">stub</span><span class="p">.</span><span class="na">connect</span><span class="p">(</span><span class="k">object</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nc">StreamObserver</span><span class="o"><</span><span class="n">Hello</span><span class="p">.</span><span class="na">Post</span><span class="o">></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onNext</span><span class="p">(</span><span class="n">post</span><span class="p">:</span><span class="w"> </span><span class="n">Hello</span><span class="p">.</span><span class="na">Post</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">mainHandler</span><span class="p">.</span><span class="na">post</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">binding</span><span class="p">.</span><span class="na">textView</span><span class="p">.</span><span class="na">text</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">post</span><span class="p">.</span><span class="na">message</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onError</span><span class="p">(</span><span class="n">t</span><span class="p">:</span><span class="w"> </span><span class="n">Throwable</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Log</span><span class="p">.</span><span class="na">e</span><span class="p">(</span><span class="s">"app"</span><span class="p">,</span><span class="w"> </span><span class="s">"gRPC error"</span><span class="p">,</span><span class="w"> </span><span class="n">t</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onCompleted</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Log</span><span class="p">.</span><span class="na">i</span><span class="p">(</span><span class="s">"app"</span><span class="p">,</span><span class="w"> </span><span class="s">"gRPC connection closed"</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">})</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>ほぼ見ての通りですって感じだけど,画面にテキストビューとボタンが設置してあって,ボタンが押されるたびその回数をカウントして,<tt class="docutils literal">button clicked: [回数]</tt> って感じのメッセージをサーバに投げてる.で,サーバから来た最新のメッセージがテキストビューに表示されるようになっていて,側から見るとボタン押すたびテキストビューの数値が更新されていく.</p>
<p>一点注意点として,テキストビューの更新の際,直接更新しないで <tt class="docutils literal">Handler</tt> というものを使っている.これは,Android の仕様として,ビューの更新はビューを作ったスレッド,今回はメインスレッドでやる必要があるらしく,<tt class="docutils literal">StreamObserver</tt> 内でやると別スレッドでの更新になってしまうのでエラーになるため.そうした時は,<tt class="docutils literal">Only the original thread that created a view hierarchy can touch its views.</tt> みたいな怒られが発生する.なので,一回メインスレッドに移譲してやる必要がある.この移譲のための <tt class="docutils literal">Handler</tt> をメインスレッドで作る (またはメインスレッドを指定して作る) とかして,やってるのが上のやつ.後は良いんじゃないんですかね.</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,モックサーバと Android アプリで gRPC 通信するやつ,全 Kotlin で書いてみた.たったこんだけ書くのに,結構ハマりポイントがあって辛かった.でも,なんとなく gradle のお作法が分かった気がする.後,Kotlin はいいぞ.</p>
<table class="docutils footnote" frame="void" id="notice-gradle-wrapper" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td>なお,gradle wrapper は生成されていて,<tt class="docutils literal"><span class="pre">gradle-wrapper.properties</span></tt> にはバージョンが記載されているので,書かなくてもいい.wrapper のバージョンを上げる時とか用に書いとくといいと言う感じ.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/04/kotlin-android-grpc.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/04/kotlin-android-grpc.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Coherent Implicit Parameter2020-03-31T07:30:54+09:002020-03-31T07:30:54+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-03-31:/blog/posts/2020/03/coherent-implicit-parameter/<p>アドホック多相を実現する方法として,型クラスがある.型クラスは,辞書渡しと呼ばれる方法により,かなり自然に elaboration …</p><p>アドホック多相を実現する方法として,型クラスがある.型クラスは,辞書渡しと呼ばれる方法により,かなり自然に elaboration ができる.ところで,この elaboration は暗黙的引数にも転用できることが知られている。特に、型クラスを搭載した Haskell では,その処理系 GHC の内部実装を利用して暗黙的引数を実現する <a class="reference external" href="https://hackage.haskell.org/package/reflection">reflection パッケージ</a> が知られている.</p>
<p>ところで,暗黙的引数の仕組みは,単純に型クラスの型システムを転用するだけでは,coherence を壊してしまう.そのため,coherence を保証しながら暗黙的引数を実現する方法がいくつか研究されている.今回は,暗黙的引数と型クラスの関係,それから少し最近考えている, coherence を保って,型クラスの仕組みを少し拡張するだけで暗黙的引数を実現するアイデアを紹介したいと思う.</p>
<div class="section" id="auto-id-1">
<h2>暗黙的引数と型クラス<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>型クラスを,型クラスを持たない言語に elaboration する方法として,型クラスを暗黙的引数と見て引数を明示するようにする変換が知られている.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">f</span>
</pre></div></td></tr></table></div>
<p>のようなプログラムは,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">C</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">instanceC_Int</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">instanceC_Int</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">C</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">d</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">instanceC_Int</span>
</pre></div></td></tr></table></div>
<p>というように elaboration される.この方法は辞書渡し (dictionary passing) と名前で知られており,Haskell の処理系 GHC でも採用されている.GHC ではメソッドが1つの型クラスは <tt class="docutils literal">newtype</tt> を使って elaboration される.例えば,上の例は GHC では次のように elaboration される:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">C</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">instanceC_Int</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">instanceC_Int</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">C</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">d</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">instanceC_Int</span>
</pre></div></td></tr></table></div>
<p>これを利用すると,次のようなプログラムが書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE ScopedTypeVariables #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Unsafe.Coerce</span>
<span class="kr">newtype</span><span class="w"> </span><span class="kt">WrapCtx</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">WrapCtx</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">r</span><span class="p">)</span>
<span class="nf">reify</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="o">.</span><span class="w"> </span><span class="p">(</span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span>
<span class="nf">reify</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unsafeCoerce</span><span class="w"> </span><span class="p">(</span><span class="kt">WrapCtx</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">WrapCtx</span><span class="w"> </span><span class="p">(</span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>実装時表現において <tt class="docutils literal">C a => r</tt> は <tt class="docutils literal">newtype C a</tt> においての <tt class="docutils literal">C a <span class="pre">-></span> r</tt> と同じであり,さらにこれは <tt class="docutils literal">a <span class="pre">-></span> r</tt> と同じであるという推論から,上のコードは正常に動くであろうということになる.なお、<tt class="docutils literal">WrapCtx</tt> で包むことにより制約の評価を遅延させている。この仕組みにより,引数を省略しても自動的にコンパイラが引数を埋めてくれるシステムが出来上がる.例えば,次のように使える:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="nf">f2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">reify</span><span class="w"> </span><span class="n">f1</span><span class="w"> </span><span class="mi">10</span>
</pre></div></td></tr></table></div>
<p>このプログラムは,推論通りに動作するなら,次のように elaboration される:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f1</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span>
<span class="nf">f2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">f1</span><span class="w"> </span><span class="p">(</span><span class="n">coerce</span><span class="w"> </span><span class="mi">10</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>実際には,もちろんこの動作はコンパイラに保証されてるわけでなく,推論通りにいかない可能性もある <a class="footnote-reference" href="#spj-offer" id="auto-id-2">[1]</a> .このハックを使ったライブラリとして <a class="reference external" href="https://hackage.haskell.org/package/reflection">reflection パッケージ</a> が知られている.その詳細については,<a class="reference external" href="https://www.schoolofhaskell.com/user/thoughtpolice/using-reflection">分かりやすいチュートリアル</a> があるのでそちらを参照するといいと思う.</p>
<p>ところで,この仕組み,次のようなコードではどう言う動きになるだろうか?:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f3</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f3</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span>
<span class="nf">f4</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f4</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">reify</span><span class="w"> </span><span class="n">f3</span><span class="w"> </span><span class="mi">10</span>
</pre></div></td></tr></table></div>
<p>このプログラムが想定していることは,2つの暗黙的引数があり,その内の1つに適用するというようなものだ.ただ、どちらの引数を適用するかは指定されていない。これは、未定義動作であり、どちらが適用されるかはコンパイラがどう制約を解決するかに依存している。<a class="reference external" href="https://hackage.haskell.org/package/reflection">reflection パッケージ</a> でもこのようなものは未定義動作を引き起こすとして注意喚起がしてある。ただ、暗黙的引数として見るなら、どの引数を使うかはちゃんとプログラマが制御できて欲しい。</p>
</div>
<div class="section" id="auto-id-5">
<h2>暗黙的引数再考<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ところで、暗黙的引数としてのフルの機能を望まないで、とりあえずそれぞれの型に1つだけ暗黙的引数が指定できるシステムを考えてみる。この場合、上記のように複数の暗黙的引数を使っても、引数の型が同じなら同じ実体を持つため、どちらの引数を使っても結果は変わらない <a class="footnote-reference" href="#conjecture-soundness" id="auto-id-6">[2]</a> 。例えば、</p>
<ul class="simple">
<li><tt class="docutils literal">Given a</tt> を暗黙的引数で <tt class="docutils literal">a</tt> 型の値が渡ってくる制約</li>
<li><tt class="docutils literal">given :: Given a => a</tt> を暗黙的引数として渡ってきた内容を取り出せる関数</li>
<li><tt class="docutils literal">Given</tt> 制約はユーザによってグローバルに定義できない</li>
</ul>
<p>とした時、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">given</span>
</pre></div></td></tr></table></div>
<p>は、<tt class="docutils literal">Given</tt> 制約が2箇所あり、辞書渡しと同じ elaboration を考えるなら、実体が2つ渡ってくることになるのでどっちの辞書を採用するかが重要になるように見える。しかし、型が同じなら同じ実体を持つという制約によって、実際はどちらを採用しても <tt class="docutils literal">f</tt> の結果は変わらない。ただ、この保証を守るため、暗黙的引数を最初に適用する部分は少し工夫が必要になる。つまり、<tt class="docutils literal">give</tt> を受け取った引数を暗黙的な引数として受け取った関数に渡すものとした時、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">give</span><span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="n">f</span>
</pre></div></td></tr></table></div>
<p>において、<tt class="docutils literal">give</tt> は <tt class="docutils literal">f</tt> の全ての暗黙的引数に関する制約を解決しないといけない。なぜなら、もし解決せずに制約を残してしまうと、上位から渡ってきた <tt class="docutils literal">g</tt> の <tt class="docutils literal">Given Int</tt> 制約が使われてしまう可能性があり、すなわち <tt class="docutils literal">f</tt> において <tt class="docutils literal">give</tt> で渡されたものと上位から渡ってきたものが混在してしまい、型が同じなら同じ実体を持つという制約を守れないからだ。よって、<tt class="docutils literal">give</tt> は制約解決において特別な仕組みを持つ何かにしなければならない。</p>
<p>ところで今までは、型によって実体は1つに決まると制約が重要ということから、それを保証するよう既存の枠組みを修正しようと流れで話してきた。ところで、発想を転換して、そもそも実体が作られる毎に型を新規に発行するということは考えられないだろうかというのが、今回紹介するアイデアの基盤になる。新規に型を発行すれば、当然型に対して実体は一つになる。具体的には、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">given</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">give</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="o">.</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span>
<span class="kr">newtype</span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">k</span><span class="o">.</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="p">)</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">k1</span><span class="w"> </span><span class="n">k2</span><span class="o">.</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k1</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k2</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k1</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k2</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f</span><span class="w"> </span><span class="n">p1</span><span class="o">#</span><span class="w"> </span><span class="n">p2</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="n">p1</span><span class="o">#</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="n">p2</span><span class="o">#</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">k</span><span class="o">.</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">g</span><span class="w"> </span><span class="n">p2</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">give</span><span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="nf">\</span><span class="n">p1</span><span class="o">#</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">p1</span><span class="o">#</span><span class="w"> </span><span class="n">p2</span><span class="o">#</span>
</pre></div></td></tr></table></div>
<p>みたいな感じでエミュレートができる。基本的には、<tt class="docutils literal">Proxy# k</tt> と rank 2 type がポイントになっていて、どんな鍵 <tt class="docutils literal">k</tt> に紐づく暗黙的引数でも大丈夫な関数の場合、鍵を新規発行して引数に紐付け関数に渡す関数が <tt class="docutils literal">give</tt> になっている。なお、<tt class="docutils literal">give</tt> / <tt class="docutils literal">given</tt> は、<a class="reference external" href="https://hackage.haskell.org/package/reflection">reflection パッケージ</a> の流儀に則って実装すれば実際に作れて、以下の感じになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">give</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="o">.</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span>
<span class="nf">give</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">unsafeCoerce</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="n">proxy</span><span class="o">#</span>
</pre></div></td></tr></table></div>
<p>もちろん、<tt class="docutils literal">Given</tt> のインスタンスが作れちゃうとまずいので、そこは隠蔽する必要があるけど。なお、型の新規発行の部分は、実際には <tt class="docutils literal">()</tt> をいつでも発行している。つまり、外部から見てどういう型を発行しているかが分からないことが大事って感じ。同じ感じのエミュレートは、存在型でも可能で、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">GivenInst</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GivenInst</span><span class="w"> </span><span class="n">a</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">GivenInstE</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kt">GivenInstE</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GivenInst</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">GivenInstE</span><span class="w"> </span><span class="n">a</span>
<span class="nf">givenInstE</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">GivenInstE</span><span class="w"> </span><span class="n">a</span>
<span class="nf">givenInstE</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GivenInstE</span><span class="w"> </span><span class="p">(</span><span class="kt">GivenInst</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GivenInst</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">give</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="o">.</span><span class="w"> </span><span class="kt">GivenInst</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span>
<span class="nf">give</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">unsafeCoerce</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">GivenInst</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="n">proxy</span><span class="o">#</span>
<span class="kr">newtype</span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="p">(</span><span class="kt">Given</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="p">)</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">k1</span><span class="w"> </span><span class="n">k2</span><span class="o">.</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k1</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k2</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k1</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k2</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f</span><span class="w"> </span><span class="n">p1</span><span class="o">#</span><span class="w"> </span><span class="n">p2</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="n">p1</span><span class="o">#</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="n">p2</span><span class="o">#</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">k</span><span class="o">.</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">g</span><span class="w"> </span><span class="n">p2</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">givenInstE</span><span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">GivenInstE</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">give</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Gift</span><span class="w"> </span><span class="nf">\</span><span class="n">p1</span><span class="o">#</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">p1</span><span class="o">#</span><span class="w"> </span><span class="n">p2</span><span class="o">#</span>
</pre></div></td></tr></table></div>
<p>ぱっと見こっちの方が複雑に見えるかもしれないけど、本質的にはこっちの方がさっきのより直感的で、新規発行されたものがどういう型か言及できないように、何かよく分からん鍵付きのインスタンスが渡ってきた時に、それを暗黙的引数として型が合ってるやつに渡せる。ところで、鍵について何も言及できないということは、暗黙的引数を受け取る関数が鍵に対して多相化されてるはずで、その直感からさっきの rank 2 type による例ができる。ところで、rank 2 type の例は多相化された関数しか相手にしていないが、こっちの例は暗黙的引数の新規発行だけは特別な仕組みになっているけど、それ以外は別に鍵を多相化しなくても利用できる。なので、例えばグローバルに1つ代表的な値が作りたいとなった時、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Global</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="kt">Global</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">True</span>
</pre></div></td></tr></table></div>
<p>みたいなんを書いといて、これを使うみたい何ができる。また、鍵自体を、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">k</span><span class="o">.</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="kt">Global</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f</span><span class="w"> </span><span class="n">p</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="o">@</span><span class="kt">Global</span><span class="w"> </span><span class="n">proxy</span><span class="o">#</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="n">p</span><span class="o">#</span>
</pre></div></td></tr></table></div>
<p>のように指定することも可能だ。鍵が単相である分には、プロテクトは外れないので、グローバルなインスタンスがコヒーレンスを守るならそれはそれで大丈夫だ。なお、ちゃんと単相であることを保証するハックとして、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Undefined</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Given</span><span class="w"> </span><span class="kt">Undefined</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">given</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">undefined</span>
</pre></div></td></tr></table></div>
<p>と機先を制しておけば、型クラスの一意性判定により多相な鍵の登録はブロックされるはず。後は、<tt class="docutils literal">GivenInst</tt> コンストラクタを隠蔽しておけば、暗黙的引数でもグローバルにもコヒーレンスが保証される仕組みが出来上がる。</p>
</div>
<div class="section" id="auto-id-7">
<h2>プリミティブなサポートへ<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ここまでのハックを言語機能としてサポートするための構文とかも色々と考えた。基本的には、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="n">keyName</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="kr">where</span><span class="w"> </span><span class="o">...</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="o">%</span><span class="n">d1</span><span class="w"> </span><span class="o">%</span><span class="n">d2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">d1</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">d2</span>
</pre></div></td></tr></table></div>
<p>ってやると、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">keyName</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="kr">where</span><span class="w"> </span><span class="o">...</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">d1</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">d2</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">d1</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">d2</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="n">d1</span><span class="w"> </span><span class="n">d2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">d1</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">d2</span>
</pre></div></td></tr></table></div>
<p>みたいなん相当になる。また、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">%</span><span class="p">(</span><span class="kt">C</span><span class="p">{</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="p">})</span><span class="w"> </span><span class="o">%</span><span class="p">(</span><span class="kt">C</span><span class="p">{</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="p">})</span>
</pre></div></td></tr></table></div>
<p>みたいなんをすると、こっちは直接 Haskell では書けないけど、<tt class="docutils literal">%(C{ m = <span class="pre">()})</span> :: exists k. C k ()</tt> みたいなんが出来上がって、いい感じに elaboration される的な。コヒーレンスチェックは完全に今まで通りグローバルなものさえチェックすれば良いはず。ただ、型制約の解決と型推論はちょっと変わるかもしれない。特に、上の例は <tt class="docutils literal">C d1 a</tt> / <tt class="docutils literal">C d2 a</tt> のインスタンスは束縛して使ってるわけだけど、<tt class="docutils literal">Semigroup</tt> のインスタンスは束縛して使ってない。これは、<tt class="docutils literal">Semigroup</tt> のどの鍵のインスタンス使うねんって話になる場合があると思うので、そこをうまいこと定義しないといけなさそう。これは型の defaulting の仕組みと大体同じことできないかなと考えてる。多相化されたままでなるべく解決できるようにして、曖昧な鍵が残っちゃったらデフォルトの鍵を使う的な。まあ、その辺ももうちょっと話詰めないとなと考えながら、特に何も考えていないのであった。</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、ちょっと拡張するとコヒーレンス満たす暗黙的引数と型クラス共通の仕組み作れそうだなみたいな話でした。</p>
<p>直感的には、コヒーレンスの正当性示せそうな気がするけど、あまり真剣には考えてない。もしかしたら壊れがあるかも。今はあまり、新機能をちゃんとまとめて実装してみることに興味がないので、多分このアイデア自体は放置されることになるんだけど、ちゃんと覚えているうちにまとめておくのは大事な気がするので、アイデアの大筋をまとめてみた。Haskell は型で一意にしかインスタンスを作らないことを前提としていて、その拡張は大体その方針と妥協しながら何とかするみたいな方向性が多く、逆に Scala はコヒーレンスチェックをある程度捨てていて、その代わり各々で管理してくださいみたいな感じなんだけど、それぞれ両極端な感じがあるけど、その中間としてこういう方針もあるよなあと考えた感じ。</p>
<p>ちゃんとアイデアまとめたんだし、どうせなら近い内に実装してみて使い勝手実験できたらなあと思っている。後、ちゃんと形式的に型システムまとめて、健全性も証明しておきたいなあ。ま、そういう感じです。なお、特に自分でやりたい欲は特に無くて (他にやりたいことたくさんあるし)、使ってみたい欲しかないので、誰か実装してくれるなら実装してくれ。</p>
<table class="docutils footnote" frame="void" id="spj-offer" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><a class="reference external" href="https://www.reddit.com/r/haskell/comments/5xqozf/implicit_parameters_vs_reflection/dek9eqg/">https://www.reddit.com/r/haskell/comments/5xqozf/implicit_parameters_vs_reflection/dek9eqg/</a> で,GHC 側は一定のサポートをするつもりだという言説が述べられている.実際のところどうなのかは分からない.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="conjecture-soundness" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[2]</a></td><td>と考えているが正しい。厳密に健全性が示せてるわけではない。</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/03/coherent-implicit-parameter.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/03/coherent-implicit-parameter.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>DerivingVia で deriving 戦略を模倣する2020-03-30T08:28:37+09:002020-03-30T08:28:37+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-03-30:/blog/posts/2020/03/deriving-strategies-by-deriving-via/<p>Haskell では、ボイラープレートは非常に嫌われており、それを撲滅するため強力な型システムの他にも幾つか機能が組み …</p><p>Haskell では、ボイラープレートは非常に嫌われており、それを撲滅するため強力な型システムの他にも幾つか機能が組み込まれている。その中で非常に強力な機能が、deriving だ。この機能は、データ型の型クラスインスタンスを、その名の通り導出してくれる機能である。Haskell 標準では、幾つかの標準の型クラスにおいて、事前に用意されたアルゴリズムによる導出ができるだけの機能だったが、GHC ではさらに3つの戦略を追加し、広範囲の型クラスの導出が行えるようになっている。特に最近入った <tt class="docutils literal">DerivingVia</tt> と呼ばれる拡張の戦略は、deriving の可能性を大いに引き上げてくれる拡張である。</p>
<p>ところで、実は <tt class="docutils literal">DerivingVia</tt> があれば他の戦略は大方模倣できる。今回は、<tt class="docutils literal">DerivingVia</tt> で各戦略を模倣しながら、簡単な紹介をしていこうと思う。</p>
<div class="section" id="auto-id-1">
<h2>型クラスインスタンスの導出<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Haskell は、データ型を代数的データ型、つまり直積と直和とプリミティブ型から構築できる型で定義する言語である。このため、型クラスが直積と直和に閉じているようなものであれば、大半インスタンス実装は同じような流れになる。例えば、<tt class="docutils literal">Eq</tt> 型クラスの例を見てみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">D1</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">D1_C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kt">D1</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">D1_C2</span><span class="w"> </span><span class="kt">Bool</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="kt">D1</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kt">D1_C1</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">y1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">D1_C1</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">y2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">y1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">y2</span>
<span class="w"> </span><span class="kt">D1_C1</span><span class="p">{}</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">D1_C2</span><span class="p">{}</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="kt">D1_C2</span><span class="p">{}</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">D1_C1</span><span class="p">{}</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="kt">D1_C2</span><span class="w"> </span><span class="n">b1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">D1_C2</span><span class="w"> </span><span class="n">b2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">b1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">b2</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">D2</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">D2_C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kt">D2</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">D2_C2</span><span class="w"> </span><span class="kt">Bool</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="kt">D2</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kt">D2_C1</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">y1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">D2_C1</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">y2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">y1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">y2</span>
<span class="w"> </span><span class="kt">D2_C1</span><span class="p">{}</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">D2_C2</span><span class="p">{}</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="kt">D2_C2</span><span class="p">{}</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">D2_C1</span><span class="p">{}</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="kt">D2_C2</span><span class="w"> </span><span class="n">b1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">D2_C2</span><span class="w"> </span><span class="n">b2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">b1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">b2</span>
</pre></div></td></tr></table></div>
<p>このプログラムにおいて、<tt class="docutils literal">D1</tt> と <tt class="docutils literal">D2</tt> は同型であり、実装もコンストラクタの名前が異なるだけでやってる内容は特に変わらない。さらには、このプログラムは直和に対するインスタンス実装と直積に対するインスタンス実装の合わせ技であり、</p>
<ol class="arabic simple">
<li>まず直和の等価性により異なるコンストラクタ同士の比較は偽に、同じコンストラクタの比較は中身の等価性で判断する</li>
<li>中身は有限直積になっているため、有限直積の等価性により、それぞれの要素をポイントワイズに比較し、その結果の論理積をとる</li>
</ol>
<p>というようになる。このようなインスタンス実装をいちいちデータ型毎に書くのは、Haskeller にとって苦痛であり、これぐらい自動的に実装して欲しいというクレームが多数寄せられることになる。そこで、直和と直積に閉じた型クラスで、標準で提供されているものに関しては、多くの場合自動的にインスタンスを実装してくれる機能が用意されている。それが、deriving だ。先ほどのプログラムは、以下のように書くこともできる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">D1</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">D1_C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kt">D1</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">D1_C2</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Eq</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">D2</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">D2_C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kt">D2</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">D2_C2</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Eq</span>
</pre></div></td></tr></table></div>
<p>随分と記述量が減り、プログラムとしても見やすくなっただろう。具体的に deriving が使える型クラスはどう言うものがあるのかについては、後述する。</p>
<p>ところで、このようなインスタンス導出のやり方は、型クラス決め打ちのものであり、それぞれの型クラスに対してコンパイラが導出アルゴリズムを用意してあげなければならない。しかし、それはあまりに拡張性がない。そこで、GHC では標準の導出戦略の他に3つの導出戦略を追加し、ユーザが一定のコードを用意さえすれば、それを利用してインスタンスを自動で導出するように拡張を加えている。それぞれの戦略は、</p>
<dl class="docutils">
<dt><tt class="docutils literal">stock</tt></dt>
<dd>標準の導出戦略で、型クラスそれぞれに対しコンパイラが導出アルゴリズムを用意し、それを使用して導出を行う。</dd>
<dt><tt class="docutils literal">newtype</tt></dt>
<dd><tt class="docutils literal">newtype</tt> で宣言したデータ型に対して使える戦略で、元の型のインスタンス実装をそのまま流用する。</dd>
<dt><tt class="docutils literal">anyclass</tt></dt>
<dd>インスタンス実装を空の実装として導出する。型クラスにデフォルトの実装が用意されてる場合、それが利用される。</dd>
<dt><tt class="docutils literal">via</tt></dt>
<dd>指定されたキャストできる範囲のデータ型のインスタンスを、流用する。</dd>
</dl>
<p>なお、型クラスとデータ型の組み合わせによって、使用できる戦略が複数ある場合がある。その場合に使用する戦略を明示的に書くことを可能にする拡張も用意されている。それが、<tt class="docutils literal">DerivingStrategies</tt> という拡張である。この拡張下では、先ほどのプログラムは次のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">D1</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">D1_C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kt">D1</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">D1_C2</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="n">stock</span><span class="w"> </span><span class="kt">Eq</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">D2</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">D2_C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kt">D2</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">D2_C2</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="n">stock</span><span class="w"> </span><span class="kt">Eq</span>
</pre></div></td></tr></table></div>
<p>なお、何も指定しない場合は、GHC が規定する <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/deriving-strategies#the-deriving-strategy-resolution-algorithm">解決の流れ</a> に沿って解決が行われる。ただ、基本的には戦略を明示するのがいいだろう <a class="footnote-reference" href="#notice-ghc-88" id="auto-id-3">[1]</a> 。以降は、この拡張を有効にしたとして、戦略を明示して書くようにする。では、3つの戦略と標準の導出戦略の詳細を見ていこうと思う。</p>
</div>
<div class="section" id="derivingvia">
<h2>DerivingVia による導出<a class="headerlink" href="#derivingvia" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MyJust</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">MyNothing</span>
</pre></div></td></tr></table></div>
<p>このデータ型に対して <tt class="docutils literal">Semigroup</tt> のインスタンス実装をしたいとする。この時、インスタンス候補は幾つかある。まず、自明なインスタンスは以下のようなものだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>もう一つ自明なものがある:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>他にも、例えば <tt class="docutils literal">Applicative</tt> のインスタンスがあれば、次のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">instance</span><span class="w"> </span><span class="kt">Functor</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="kr">where</span><span class="w"> </span><span class="o">...</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Applicative</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="kr">where</span><span class="w"> </span><span class="o">...</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="o"><$></span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">x2</span>
</pre></div></td></tr></table></div>
<p>さらに <tt class="docutils literal">Alternative</tt> のインスタンスがあれば、次のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">instance</span><span class="w"> </span><span class="kt">Alternative</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="kr">where</span><span class="w"> </span><span class="o">...</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o"><|></span><span class="w"> </span><span class="n">x2</span>
</pre></div></td></tr></table></div>
<p>これらのインスタンス実装は、<tt class="docutils literal">MyMaybe</tt> 固有のものではなく、条件さえ満たしていれば他のデータ型にも流用できそうである。また、インスタンス実装が、このデータ型固有のものではなく、共通の自然な導出によるものであることを明示できれば、それはコードを管理する上でもアドバンテージになるだろう。<tt class="docutils literal">DerivingVia</tt> はまさにそのような導出戦略を明示できる機能だ。上記のインスタンス実装は、<tt class="docutils literal">DerivingVia</tt> を使えばそれぞれ次のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE DerivingVia #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Data.Semigroup</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Data.Monoid</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Last</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">First</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Ap</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Alt</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span>
</pre></div></td></tr></table></div>
<p>これは、気持ち的にはそれぞれ次のようにインスタンスを生成する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE TypeApplications #-}</span>
<span class="cm">{-# LANGUAGE ScopedTypeVariables #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Data.Coerce</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">Last</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">))</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="o">@</span><span class="p">(</span><span class="kt">Last</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">))</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">First</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">))</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="o">@</span><span class="p">(</span><span class="kt">First</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">))</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">Ap</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="o">@</span><span class="p">(</span><span class="kt">Ap</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">Alt</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="o">@</span><span class="p">(</span><span class="kt">Alt</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>気持ち的にはと言ったのは、最終的に制約部分が単純化され、最低限の制約に展開されるからだ <a class="footnote-reference" href="#notice-semigroup-has-multi-methods" id="auto-id-4">[2]</a> 。例えば、<tt class="docutils literal">Semigroup (Last (MyMaybe a))</tt> や <tt class="docutils literal">Semigroup (First (MyMaybe a))</tt> は常に制約が満たされるので除去され、<tt class="docutils literal">Semigroup (Ap MyMaybe a)</tt> や <tt class="docutils literal">Semigroup (Alt MyMaybe a)</tt> はそれぞれ <tt class="docutils literal">(Applicative MyMaybe, Semigroup a)</tt>、<tt class="docutils literal">Alternative MyMaybe</tt> に展開される。さらに単純化によって、<tt class="docutils literal">Applicative MyMaybe</tt> や <tt class="docutils literal">Alternative MyMaybe</tt> はその場で計算され、インスタンスがない場合はエラーになる。なお、単純化の計算結果を使いたくない場合、<tt class="docutils literal">StandaloneDeriving</tt> を使うと良い。<tt class="docutils literal">StandaloneDeriving</tt> はインスタンス導出を、データ型宣言とは独立にできる GHC 拡張で、インスタンスのヘッド部分を明示することができる。今回の場合は、上の <tt class="docutils literal">DerivingVia</tt> を使った例は次のようにも書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE StandaloneDeriving #-}</span>
<span class="kr">deriving</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Last</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">deriving</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">First</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">deriving</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Ap</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="c1">-- または、推奨されないが Applicative インスタンスの判定を、次のように遅延させることも可能</span>
<span class="kr">deriving</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Ap</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="p">(</span><span class="kt">Applicative</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="p">,</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">deriving</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Alt</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="c1">-- または、Ap と同じく Alternative インスタンスの判定を、次のように遅延させることも可能</span>
<span class="kr">deriving</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Alt</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">Alternative</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">StandaloneDeriving</tt> を使う場合は、制約の単純化は必要ないため、<tt class="docutils literal">DerivingVia</tt> が行うことは、主に <tt class="docutils literal">coerce</tt> によって実装元から実装を持ってくることになる。もちろん、<tt class="docutils literal">coerce</tt> できないものから実装を持ってくることはできないので、例えば次のようなことは書けない:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">deriving</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>この場合、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="o">@</span><span class="p">(</span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>という実装が作られることになり、<tt class="docutils literal">Coercible (Maybe a <span class="pre">-></span> Maybe a <span class="pre">-></span> Maybe a) (MyMaybe a <span class="pre">-></span> MyMaybe a <span class="pre">-></span> MyMaybe a)</tt> の制約が満たされなければならない。<tt class="docutils literal"><span class="pre">(->)</span></tt> は両方 <tt class="docutils literal">representation</tt> ロールを持つ <a class="footnote-reference" href="#notice-runtimereps" id="auto-id-5">[3]</a> ので、この制約は <tt class="docutils literal">Coercible (Maybe a) (MyMaybe a)</tt> が成り立つかによって決まる。そして、この制約は残念ながら成り立たない。よって、上記のインスタンス実装は型検査に失敗する。</p>
<p>このように <tt class="docutils literal">DerivingVia</tt> は全ての継承できそうなインスタンスを継承できるわけではないが、かなり広い範囲のインスタンスの自動実装が可能だ。しかも、その仕組みはみた通りかなり単純だ。もし、あるクラスがインスタンスを自動で導出できそうな状況であれば、</p>
<ol class="arabic simple">
<li>そのインスタンスを実装する <tt class="docutils literal">newtype</tt> を作る</li>
<li>その <tt class="docutils literal">newtype</tt> を元に、<tt class="docutils literal">DerivingVia</tt> を使う</li>
</ol>
<p>という手順で、ユーザ定義により自動でインスタンス導出を行うことができる。この手順は通常の Haskell プログラミングからそうかけ離れたものでなく、マクロなどのメタプログラミングも必要ない、かなり強力な機能だ。さらには、<tt class="docutils literal">DerivingVia</tt> は他の導出戦略を模倣可能だ。では、他の戦略を見ていこう。</p>
</div>
<div class="section" id="generalizednewtypederiving-gnd">
<h2>GeneralizedNewtypeDeriving (GND) による導出<a class="headerlink" href="#generalizednewtypederiving-gnd" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal">newtype</tt> 戦略は、<tt class="docutils literal">newtype</tt> によって定義されたデータ型に特化した戦略だ。この戦略は、<tt class="docutils literal">GeneralizedNewtypeDeriving</tt>、通称 GND という拡張で利用可能だ。この戦略を使って、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE GeneralizedNewtypeDeriving #-}</span>
<span class="kr">newtype</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="p">(</span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kr">newtype</span><span class="w"> </span><span class="kt">Semigroup</span>
</pre></div></td></tr></table></div>
<p>と書くと、気分的には次のようなインスタンス実装が作られる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="o">@</span><span class="p">(</span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>なお、制約部分は、最終的に <tt class="docutils literal">DerivingVia</tt> の時と同じく単純化され、<tt class="docutils literal">Semigroup a</tt> に置き換わる。なお、<tt class="docutils literal">StandaloneDeriving</tt> で遅延できる話も同じだ。さらに、インスタンス実装の形も良くにている。実際、<tt class="docutils literal">newtype</tt> 戦略は、<tt class="docutils literal">DerivingVia</tt> で簡単に書き直せる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE DerivingVia #-}</span>
<span class="kr">newtype</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MyMaybe</span><span class="w"> </span><span class="p">(</span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span>
</pre></div></td></tr></table></div>
<p>見ての通りそのままになる。冗長ではあるが、この方がどのデータ型のインスタンスを流用するのかが分かりやすいと思う。これについては、いいだろう。GND は <tt class="docutils literal">DerivingVia</tt> の特殊なバージョンということができるだろう。</p>
</div>
<div class="section" id="deriveanyclass">
<h2>DeriveAnyClass による導出<a class="headerlink" href="#deriveanyclass" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、Haskell 業界には、一切メソッドを実装しなくても、自動的にメソッドを作ってくれるクラスがいくつかある。代表的なものが <tt class="docutils literal">Hashable</tt> クラスだ。<tt class="docutils literal">Hashable</tt> クラスは、<tt class="docutils literal">hashable</tt> パッケージで提供されているクラスで、<tt class="docutils literal"><span class="pre">unordered-containers</span></tt> パッケージなどハッシュ値の計算を必要とするデータ構造を提供するパッケージにおいて、ハッシュ値を計算できるクラスとして用いられている。ただ、ハッシュ値の計算自体は冗長なのに対しほぼボイラープレート化することが多い。そこで、デフォルトで <tt class="docutils literal">Generic</tt> のインスタンスがあれば自動でハッシュ値の計算方法を実装してくれるようになっている。このため、ユーザは特になんのメソッドも書かずにインスタンスを定義できる。具体的には、次のようにだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Hashable</span><span class="w"> </span><span class="kt">A</span>
</pre></div></td></tr></table></div>
<p>なお、このインスタンス実装は、導出戦略としても使える。それを行うのが、<tt class="docutils literal">anyclass</tt> 戦略だ。<tt class="docutils literal">anyclass</tt> 戦略は <tt class="docutils literal">DeriveAnyClass</tt> 拡張で利用可能になっており、次のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE DeriveAnyClass #-}</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="n">anyclass</span><span class="w"> </span><span class="kt">Hashable</span>
</pre></div></td></tr></table></div>
<p>なお、名前の由来は、この戦略がその名の通りどのクラスに対しても適用可能なことから来ている。実は、Haskell はどのクラスに対しても空の実装を持つインスタンスが書ける。例えそのクラスが実装を必要とするメソッドを持っていたとしてもだ。例えば、次のようなことが書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="kt">A</span>
</pre></div></td></tr></table></div>
<p>このコードは、概ね次のように展開される:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">undefined</span>
</pre></div></td></tr></table></div>
<p>実際には、もう少し丁寧なエラーメッセージが付いたりするが、実行時エラーになるのは変わらない。<tt class="docutils literal">anyclass</tt> 戦略は、これと同じことをするので、上記のことは次のようにも書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="n">anyclass</span><span class="w"> </span><span class="kt">Semigroup</span>
</pre></div></td></tr></table></div>
<p>ただこれはあまりにもあんまりなので、GHC では独自に実装するべきメソッドが管理されていて、そのメソッドが実装されていないと警告が出るようになっている。</p>
<p>さて、実装がデータ型によらず決まるというのは、<tt class="docutils literal">DerivingVia</tt> お得意というかそもそもそういう時のために生まれてきたという状況で、<tt class="docutils literal">anyclass</tt> 戦略は <tt class="docutils literal">DerivingVia</tt> で自然に模倣できる。例えば、<tt class="docutils literal">Hashable</tt> の場合、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">FromGeneric'</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">FromGeneric</span><span class="w"> </span><span class="n">a</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">FromGeneric</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">FromGeneric'</span><span class="w"> </span><span class="p">(</span><span class="kt">Rep</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="p">(</span><span class="kt">Generic</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">Rep</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">~</span><span class="w"> </span><span class="n">r</span><span class="p">,</span><span class="w"> </span><span class="kt">CanDeriveHashable</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Hashable</span><span class="w"> </span><span class="p">(</span><span class="kt">FromGeneric'</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="o">...</span>
</pre></div></td></tr></table></div>
<p>というようなフレームワークを用意しておけば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="n">stock</span><span class="w"> </span><span class="kt">Generic</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Hashable</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">FromGeneric</span><span class="w"> </span><span class="kt">A</span>
</pre></div></td></tr></table></div>
<p>と書ける。こちらの方が、どういうインスタンスの導出戦略を使っているかが明示的で分かりやすいだろう。なお、もちろん、危険な方のインスタンス導出も、次のように模倣できる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">AnyClass</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">AnyClass</span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">AnyClass</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">AnyClass</span><span class="w"> </span><span class="kt">A</span>
</pre></div></td></tr></table></div>
<p>ただ、このような使用用途はもちろん推奨されない。</p>
<p><tt class="docutils literal">anyclass</tt> 戦略では危険な導出戦略と安全な導出戦略が混在していたわけで、それを見分ける方法は警告だけだったわけだが、<tt class="docutils literal">DerivingVia</tt> では元とする型によってそれをきっちりと分けることができる。さらに、<tt class="docutils literal">anyclass</tt> を前提とする場合デフォルト実装は一つしか提供できない。ところが、<tt class="docutils literal">DerivingVia</tt> はいくらでも戦略を増やすことができる。ハッシュ値の計算は、幾つかアルゴリズムの選択肢があるが、<tt class="docutils literal">DerivingVia</tt> と型レベルプログラミングを使えばどれを使用するか自由に選べたりする。なお、<tt class="docutils literal">anyclass</tt> 戦略でできて <tt class="docutils literal">via</tt> 戦略ではできない例は思いついていないんだけど、これはもしかしたらあるかもしれない <a class="footnote-reference" href="#conjecture-anyclass-by-via" id="auto-id-6">[4]</a> 。誰か知ってたら教えて欲しい。大半は <tt class="docutils literal">via</tt> 戦略で模倣できると思うので、<tt class="docutils literal">anyclass</tt> 戦略もやはり <tt class="docutils literal">via</tt> 戦略の特殊なバージョンと思えるだろう。</p>
</div>
<div class="section" id="auto-id-7">
<h2>標準の導出戦略<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>最後は、<tt class="docutils literal">stock</tt> 戦略の紹介になる。と言っても、これに関してはあまり言うことはない。<tt class="docutils literal">deriving Eq</tt> とか書いておくと、GHC が勝手にどうやってるのか知らんけどインスタンス実装してくれるやつである。最初に触れたように、これは基本的に直積と直和からインスタンスを類推している。なお、<tt class="docutils literal">StandaloneDeriving</tt> を使わない場合は、型検査が自明に通るようなインスタンスしか実装されず、<tt class="docutils literal">DerivingVia</tt> などに比べコンパイル時間も削減できたりする。標準の範囲では、次のクラスが <tt class="docutils literal">stock</tt> 戦略で導出可能だ:</p>
<dl class="docutils">
<dt><tt class="docutils literal">Eq</tt></dt>
<dd>等価性判定ができるクラス</dd>
<dt><tt class="docutils literal">Ord</tt></dt>
<dd>順序比較ができるクラス</dd>
<dt><tt class="docutils literal">Enum</tt></dt>
<dd>整列ができるクラス</dd>
<dt><tt class="docutils literal">Bounded</tt></dt>
<dd>上限と下限があるクラス</dd>
<dt><tt class="docutils literal">Show</tt></dt>
<dd>文字列表示ができるクラス</dd>
<dt><tt class="docutils literal">Read</tt></dt>
<dd>文字列からの読み込みができるクラス</dd>
<dt><tt class="docutils literal">Ix</tt></dt>
<dd>上下を設定した範囲内で整列ができるクラス</dd>
</dl>
<p>GHC では他に、幾つかのクラスの導出ができるようになっている。GHC 8.8 現在で追加されているクラスは、以下の通りだ <a class="footnote-reference" href="#notice-derive-data-typeable" id="auto-id-8">[5]</a> :</p>
<dl class="docutils">
<dt><tt class="docutils literal">Data</tt></dt>
<dd>型を超えてデータを一般的に扱うことができるクラス。<tt class="docutils literal">DeriveDataTypeable</tt> 拡張が必要。</dd>
<dt><tt class="docutils literal">Generic</tt> / <tt class="docutils literal">Generic1</tt></dt>
<dd>データ型のメタ情報が取得できるクラス。<tt class="docutils literal">DeriveGeneric</tt> 拡張が必要。</dd>
<dt><tt class="docutils literal">Foldable</tt></dt>
<dd>リストへの変換が可能なクラス。<tt class="docutils literal">DeriveFoldable</tt> 拡張が必要。</dd>
<dt><tt class="docutils literal">Functor</tt></dt>
<dd>任意の関数を対象の高次なデータ型への関数へと持ち上げることができるクラス。<tt class="docutils literal">DeriveFunctor</tt> 拡張が必要。</dd>
<dt><tt class="docutils literal">Traversable</tt></dt>
<dd>文脈付きの探索ができるクラス。<tt class="docutils literal">DeriveTraversable</tt> 拡張が必要。</dd>
<dt><tt class="docutils literal">Lift</tt></dt>
<dd>TemplateHaskell 上の構文木に変換できるクラス。<tt class="docutils literal">DeriveLift</tt> 拡張が必要。</dd>
</dl>
<p>ここで挙げたクラスを導出したい場合、特に何かこだわりがあるわけでなく、<tt class="docutils literal">stock</tt> 戦略で導出可能なら、自前でインスタンスを書かず <tt class="docutils literal">stock</tt> 戦略を使うことをお勧めする。これは、無用な混乱を避けるためだ。</p>
<p>ところで、<tt class="docutils literal">stock</tt> 戦略があるのであまり実益としての意味はないのだが、<tt class="docutils literal">stock</tt> 戦略の多くは <tt class="docutils literal">Generic</tt> と <tt class="docutils literal">DerivingVia</tt> で模倣できる。例えば、<tt class="docutils literal">Eq</tt> クラスの導出は次のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE ScopedTypeVariables #-}</span>
<span class="kr">newtype</span><span class="w"> </span><span class="kt">FromGeneric'</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">FromGeneric</span><span class="w"> </span><span class="n">a</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">FromGeneric</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">FromGeneric'</span><span class="w"> </span><span class="p">(</span><span class="kt">Rep</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="p">(</span><span class="kt">Generic</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">~</span><span class="w"> </span><span class="kt">Rep</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="p">(</span><span class="n">r</span><span class="w"> </span><span class="nb">()</span><span class="p">))</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="p">(</span><span class="kt">FromGeneric'</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kt">FromGeneric</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kt">FromGeneric</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">from</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="p">(</span><span class="n">from</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="nb">()</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="n">stock</span><span class="w"> </span><span class="kt">Generic</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">FromGeneric</span><span class="w"> </span><span class="kt">A</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">stock</tt> 戦略に比べ変換を一度かます必要はあるものの、実際の計算フロー的には <tt class="docutils literal">stock</tt> 戦略で作られたインスタンスと上のインスタンスは、同じことをしている。<tt class="docutils literal">Ord</tt> やちょっと工夫は必要だが他の標準のクラスも同じような方法で導出するシステムを作れるし、GHC で用意されてるものも <tt class="docutils literal">Generic1</tt> から作れる。ここから分かるように、<tt class="docutils literal">DerivingVia</tt> は結構強力な機能になる。</p>
</div>
<div class="section" id="auto-id-9">
<h2>おまけ: デフォルト実装を模倣する<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて、Haskell にはクラスメソッドのデフォルト実装という機能がある。インスタンス定義において、未実装のメソッドは、デフォルト実装が用意されていればその実装で埋められ、無ければ実行時エラーが埋められる。デフォルト実装は、通常実装する必要のあるメソッドを使って実装されることが多い。例えば、今まで誤魔化してきたのだが、<tt class="docutils literal">Semigroup</tt> は実際には3つのメソッドを持ち、次のように定義される:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="n">sconcat</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">NonEmpty</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="n">sconcat</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="kt">:|</span><span class="w"> </span><span class="n">as</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">as</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="kt">:</span><span class="n">cs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">cs</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="n">stimes</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Integral</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="n">stimes</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">stimes</tt> のデフォルト実装はちょっと複雑になるので省略する。<tt class="docutils literal">sconcat</tt> のデフォルト実装を見ると分かる通り、<tt class="docutils literal"><span class="pre">(<>)</span></tt> を定義内で使っているが、後は依存が完結している。よって、<tt class="docutils literal"><span class="pre">(<>)</span></tt> の実装さえあれば、この実装は動くようになっている。ところで、<tt class="docutils literal">deriving</tt> とは少々外れるが、このようなデフォルト実装を <tt class="docutils literal">DerivingVia</tt> で模倣することもできる。次のようにだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE ScopedTypeVariables #-}</span>
<span class="cm">{-# LANGUAGE TypeApplications #-}</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">SemigroupMinimal</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">minimalAppend</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="kr">newtype</span><span class="w"> </span><span class="kt">FromMinimal</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">FromMinimal</span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">SemigroupMinimal</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="p">(</span><span class="kt">FromMinimal</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">minimalAppend</span><span class="w"> </span><span class="o">@</span><span class="n">a</span>
<span class="w"> </span><span class="n">sconcat</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">sconcatDefault</span><span class="w"> </span><span class="o">@</span><span class="n">a</span>
<span class="w"> </span><span class="n">stimes</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">stimeDefault</span><span class="w"> </span><span class="o">@</span><span class="n">a</span>
<span class="nf">sconcatDefault</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">SemigroupMinimal</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">NonEmpty</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">sconcatDefault</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="nf">stimesDefault</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">SemigroupMinimal</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">Integral</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">stimesDefault</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
</pre></div></td></tr></table></div>
<p>このフレームワークを使えば、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o"><></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
</pre></div></td></tr></table></div>
<p>は、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Semigroup</span><span class="w"> </span><span class="n">via</span><span class="w"> </span><span class="kt">FromMinimal</span><span class="w"> </span><span class="kt">A</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">SemigroupMinimal</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">minimalAppend</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
</pre></div></td></tr></table></div>
<p>と書ける。むしろ冗長かしていてボイラープレートは増えているが、その代わり暗黙的なデフォルト実装は明示できる。また、デフォルト実装は一通りの実装パターンしか選べないが、他にもデフォルト実装のパターンがある場合、このような工夫は生きてくる。その場合、<tt class="docutils literal">DerivingVia</tt> でどのデフォルト実装セットを使うか選べるからだ。また、デフォルト実装のパターンは後からいくらでも追加できるし、サードパーティの人も追加できるようになる。このように単純な仕組みに対して、実装の可能性がかなり広がるのが、<tt class="docutils literal">DerivingVia</tt> の強力なところだと思う。</p>
</div>
<div class="section" id="auto-id-10">
<h2>まとめ<a class="headerlink" href="#auto-id-10" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで、各導出戦略の紹介、もとい <tt class="docutils literal">DerivingVia</tt> の紹介でした。これはかなり未来感じる機能だと思うし、少なくとも <tt class="docutils literal">newtype</tt> / <tt class="docutils literal">anyclass</tt> 戦略はもう必要なくない? みたいな気持ちでいる。</p>
<p>なお、デフォルト実装も上手く扱えるよう <tt class="docutils literal">DerivingVia</tt> を拡張するのはどうすればいいかな的なことは、たまに考えてる。<tt class="docutils literal">DerivingVia</tt> の前後、つまり実装に必要なメソッド定義を与えるのと、<tt class="docutils literal">DerivingVia</tt> で定義されたメソッドを上書きするみたいな機能があると、もっと柔軟になりそうだけど、それはそれで機能過多かもしれないとも思う。<tt class="docutils literal">deriving</tt> 自体は、インスタンス実装を隠蔽できるという性質も持っていて、<tt class="docutils literal">DerivingVia</tt> はさらにその機能を強力にできるという側面もある。まあ、色々可能性ひろがリングね。てことで、今回は以上。</p>
<table class="docutils footnote" frame="void" id="notice-ghc-88" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[1]</a></td><td>なお、GHC 8.10 からは戦略を指定しないで <tt class="docutils literal">newtype</tt> / <tt class="docutils literal">anyclass</tt> 戦略を使おうとすると、警告が出るようになった。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-semigroup-has-multi-methods" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[2]</a></td><td>さらに厳密に言えば、<tt class="docutils literal">coerce</tt> されるのは <tt class="docutils literal"><span class="pre">(<>)</span></tt> メソッドだけではないというのもある。<tt class="docutils literal">Semigroup</tt> は他に <tt class="docutils literal">sconcat</tt>、<tt class="docutils literal">stimes</tt> メソッドを持っているので、これらも <tt class="docutils literal">coerce</tt> される。ただ、ここではそれらを省略している。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-runtimereps" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[3]</a></td><td>厳密には、<tt class="docutils literal"><span class="pre">(->)</span></tt> は GHC 8.8 現在だと4つの引数を持ち、<tt class="docutils literal"><span class="pre">(->)::</span> (q :: RuntimeRep) <span class="pre">-></span> (r :: RuntimeRep) <span class="pre">-></span> (a :: TYPE q) <span class="pre">-></span> (b :: TYPE r) <span class="pre">-></span> Type</tt> という種をしている。このうち、最初の <tt class="docutils literal">q</tt>、<tt class="docutils literal">r</tt> が <tt class="docutils literal">nominal</tt> で、次の <tt class="docutils literal">a</tt>、<tt class="docutils literal">b</tt> が <tt class="docutils literal">representational</tt> である。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="conjecture-anyclass-by-via" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[4]</a></td><td>おそらくないと思う。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-derive-data-typeable" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-8">[5]</a></td><td>実はもう一個 <tt class="docutils literal">Typeable</tt> と言うクラスが、<tt class="docutils literal">DeriveDataTypeable</tt> で導出可能だ。しかし、ある問題からこれは非推奨になっている。詳しくは、<a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/-/wikis/typeable">https://gitlab.haskell.org/ghc/ghc/-/wikis/typeable</a> を覗いてみるといいと思う。なお、現状全てのデータ型は <tt class="docutils literal">Typeable</tt> インスタンスが自動で作られるようになっており、独自にインスタンスを書いたり <tt class="docutils literal">deriving</tt> を使ったりしても完全に無視される。</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/03/deriving-strategies-by-deriving-via.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/03/deriving-strategies-by-deriving-via.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>遅延評価でデバッグが困難になる状況2020-03-29T08:12:41+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-03-29:/blog/posts/2020/03/haskell-lazy-debug-problem/<p>先日、Haskell 界隈で遅延評価によってデバッグがし辛いのはどんな時かと言う話があった。見た感じ、遅延評価によってデ …</p><p>先日、Haskell 界隈で遅延評価によってデバッグがし辛いのはどんな時かと言う話があった。見た感じ、遅延評価によってデバッグのしにくさはそんなに変わらないと言う意見が結構あり、個人的には衝撃だった。僕自身は遅延評価にだいぶヘイトを溜めてる人なので、どういう状況でデフォルト遅延評価が嫌かを実感できる問題を作った。この問題を解けば、きっとヘイトを共有できるはずってわけ。一緒に地獄に落ちような。</p>
<p>なお、かなり主観に寄っていて、結構書き殴ってる部分が多いので、厳密な議論をするにはあまり良い例ではないかもしれない。個人的には、備忘録的な意味合いも強くて、今まで詰まったやつをまとめておくかみたいな感じでもある。</p>
<p>先に結論を書いておくと、</p>
<ul class="simple">
<li>プログラム自体が大きくて <a class="footnote-reference" href="#simple-example" id="auto-id-2">[1]</a></li>
<li>複雑な制御構造をしていて</li>
<li><dl class="first docutils">
<dt>(optional) 以下のいずれかの条件を満たす</dt>
<dd><ul class="first last">
<li>遅延評価を機能として使っている</li>
<li>デバッグ対象が効率に関するバグである</li>
</ul>
</dd>
</dl>
</li>
</ul>
<p>なプログラムは、遅延評価によるデバッグの難易度が高い傾向にあると思う。後、遅延評価によるデバッグ作業は、正格評価のそれに比べ、経験がかなりものを言うと思っている。</p>
<div class="section" id="auto-id-3">
<h2>問題1: 無限ループするパーサコンビネータ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Haskell にはモナディックパーサコンビネータと呼ばれるライブラリ群がある。これは、名前の通りプリミティブなパーサをモナディックに繋げていくことで、目的のパーサを書けるようなライブラリで、<tt class="docutils literal">Parsec</tt> の名前を冠する系統が有名だ。パーサコンビネータのチュートリアルは、Hutton & Meijer <a class="footnote-reference" href="#hutton-1998" id="auto-id-4">[2]</a> <a class="footnote-reference" href="#hutton-1996" id="auto-id-5">[3]</a> <a class="footnote-reference" href="#notice-hutton-meijer-performance" id="auto-id-6">[4]</a> がおすすめなので、見てみるといいと思う。Hutton & Meijer では、パーサを <tt class="docutils literal">StateT String []</tt> で作るわけだけど、ここではそれを拡張して、</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">Parser</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Parser</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">unParser</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">ParseState</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">ParseResult</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">ParseState</span><span class="w"> </span><span class="n">t</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">Position</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Int</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">ParseState</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">ParseState</span><span class="w"> </span><span class="kt">Position</span><span class="w"> </span><span class="p">[</span><span class="n">t</span><span class="p">]</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">ParseResult</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">ParseSuccess</span><span class="w"> </span><span class="p">(</span><span class="kt">NonEmpty</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">ParseFailure</span><span class="w"> </span><span class="p">[(</span><span class="kt">Position</span><span class="p">,</span><span class="w"> </span><span class="kt">String</span><span class="p">)]</span>
</pre></div></td></tr></table></div>
<p>のようなパーサを使っていくことにする。Hutton & Meijer との違いは、</p>
<ul class="simple">
<li>状態が後読むべき文字列 <tt class="docutils literal">String</tt> でなく、現在の位置と後読むべき <tt class="docutils literal">t</tt> 型トークンの列になってること</li>
<li>パース結果が空だった場合、エラーとみなして、エラー位置とメッセージを載せられるようになってること</li>
</ul>
<p>だ。<tt class="docutils literal">ParseResult</tt> はそれ単体でモナドになり、結果的に <tt class="docutils literal">Parser</tt> は <tt class="docutils literal">StateT (ParseResult t) ParseResult</tt> と同じと考えれば、やはりモナドになる。このパーサを使って、以下の文法を持つ言語をパースしていきたい:</p>
<img alt="Haskell の型クラスとか諸々ないサブセット" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2020/03/haskell-lazy-debug-problem/haskell-lazy-debug-problem/simple-language.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>d</mi><mi>e</mi><mi>n</mi><mi>t</mi></mrow><annotation encoding="application/x-tex">\mathit{ident}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathit">ident</span></span></span></span></span></span>、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>y</mi><mi>m</mi><mi>b</mi><mi>o</mi><mi>l</mi></mrow><annotation encoding="application/x-tex">\mathit{symbol}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">symbol</span></span></span></span></span></span>、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>n</mi><mi>t</mi><mi>e</mi><mi>g</mi><mi>e</mi><mi>r</mi></mrow><annotation encoding="application/x-tex">\mathit{integer}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8498em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">integer</span></span></span></span></span></span> やその他の記号は字句解析済で渡ってくるとする。AST は以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">App</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">InfixApp</span><span class="w"> </span><span class="kt">Expr</span><span class="w"> </span><span class="kt">Var</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Abs</span><span class="w"> </span><span class="kt">Var</span><span class="w"> </span><span class="kt">Expr</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Var</span><span class="w"> </span><span class="kt">Var</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Lit</span><span class="w"> </span><span class="kt">Lit</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">Lit</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Int</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">Var</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">String</span>
</pre></div></td></tr></table></div>
<p>で、文法で示した属性規則に従って、AST を得たいわけだ。さて、勢いで書いてみたプログラムが、<a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2020/03/haskell-lazy-debug-problem/haskell-lazy-debug-problem/Problem01.html">Problem01.hs</a> になる。ところが、動かしてみるとどうもどこかで無限ループしているようだ。最終的に、あなたにはこのプログラムを4つの例の結果がちゃんと返るように修正して欲しい。</p>
<p>この問題の修正例は、<a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2020/03/haskell-lazy-debug-problem/haskell-lazy-debug-problem/Problem01A.html">Problem01A.hs</a> になる。</p>
<p>さて、一般にパーサコンビネータライブラリは遅延評価を機能として利用している。これは、複雑なパーサのデバッグにおいて、個人的には常に厄介だ。今回の問題は、かなり難易度を緩めにしていて <a class="footnote-reference" href="#notice-problem-hardness" id="auto-id-7">[5]</a> 、常に無限ループが起こるわけだが、これがある (かなり特殊なケースの) プログラムでしか無限ループが起きないことを想定してみて欲しい。実際に、無限ループの原因を特定した人なら分かるはずだが、このような出来事は結構頻繁に起こる。このデバッグはかなりしんどく、なんならデバッグ文表示のために、変に評価を入れようものなら、通常問題ないところまで無限ループし始めるという大惨事が発生する。</p>
<p>また、パーサコンビネータのデバッグは、</p>
<ul class="simple">
<li>パーサの構築の際に問題があるのか</li>
<li>パース結果の操作に問題があるのか</li>
</ul>
<p>の切り分けが難しい。そのために、色々問題を切り分ける必要が出てくるが、その際にも遅延評価は結構悩みの種になる。なぜなら、パーサの構築と結果の操作が同時進行で、しかもデータの依存関係に沿って起こるからだ。多くの場合、データの依存関係とプログラマが想定する時系列はあっていない事が多く、結果トレースがめちゃくちゃになる。</p>
<p>で、解決策だけど、僕はパーサコンビネータを捨てて、</p>
<ul class="simple">
<li>複雑なパースには Happy などのパーサジェネレータ</li>
<li>簡単なパースには、正規表現</li>
</ul>
<p>を使うようになった。これはデバッグが辛い事だけが理由ではないけれど、この理由も大きい。なお、字句解析など、比較的簡単な、でも正規表現だけではやりにくい奴については、パーサコンビネータを使うこともある。</p>
</div>
<div class="section" id="zipper">
<h2>問題2: Zipper による複雑怪奇な評価器<a class="headerlink" href="#zipper" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>次のような構造を考える:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Inst</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GetChild</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="p">(</span><span class="kt">Inst</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Put</span><span class="w"> </span><span class="kt">Char</span><span class="w"> </span><span class="p">[</span><span class="kt">Inst</span><span class="w"> </span><span class="n">a</span><span class="p">]</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Var</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Bottom</span>
</pre></div></td></tr></table></div>
<p>この構造は、次のような意味論を持つ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Value</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">VPut</span><span class="w"> </span><span class="kt">Char</span><span class="w"> </span><span class="p">[</span><span class="kt">Value</span><span class="p">]</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">VBottom</span>
<span class="nf">evalInst</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Value</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Inst</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Value</span>
<span class="nf">evalInst</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">\</span><span class="kr">case</span>
<span class="w"> </span><span class="kt">GetChild</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">getChild</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">t</span>
<span class="w"> </span><span class="kt">Put</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">ts</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">VPut</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">ts</span><span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="kt">Var</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="kt">Bottom</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">VBottom</span>
<span class="nf">getChild</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Value</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Value</span>
<span class="nf">getChild</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">\</span><span class="kr">case</span>
<span class="w"> </span><span class="kt">VPut</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">ts</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">drop</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">ts</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="n">t</span><span class="kt">:</span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">t</span>
<span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">VBottom</span>
<span class="w"> </span><span class="n">t</span><span class="o">@</span><span class="kt">VBottom</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">t</span>
</pre></div></td></tr></table></div>
<p>つまり、<tt class="docutils literal">Inst a</tt> は、文字による木とエラー値を値に持ち、<tt class="docutils literal">GetChild</tt> という木の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span></span> 番目の子供を取得するプリミティブな操作と変数が入ったシステムになる。ところで、このシステムは書き換えシステムとして実装することもできる。今回は、Zipper を使って変数への代入を行わない書き換えシステムを実装してみたい。さて、勢いで書いてみたプログラムが、<a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2020/03/haskell-lazy-debug-problem/haskell-lazy-debug-problem/Problem02.html">Problem02.hs</a> になる。ところが、動かしてみても、結果が著しく異なる。最終的に、あなたにはこのプログラムを4つの例の結果がちゃんと返るように修正して欲しい。</p>
<p>この問題の修正例は、<a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2020/03/haskell-lazy-debug-problem/haskell-lazy-debug-problem/Problem02A.html">Problem02A.hs</a> になる。</p>
<p>さて、Haskell のプログラム例の多くは、再帰的な木に対してそれに沿って再帰を回すというものである。ところが、現実世界ではその形に沿わない状況も多い。その典型例がグラフ処理である。グラフは、あっちにいったりこっちに行ったりということを条件によって行う。また、停止性の条件も非自明な場合が多い。Haskell でグラフを扱うのは、少し厄介なので、今回はその気分を Zipper を使って再現してみた。こちらも難易度は控えめにしてある <a class="footnote-reference" href="#notice-problem-hardness-2" id="auto-id-8">[6]</a> 。</p>
<p>遅延評価は、一般に複雑な制御構造を持つプログラムのデバッグ難易度を結構上げる代物だと思う。というのは、そういうプログラムは、多くの場合制御フローが間違っているわけで、どこのフローが間違っているかを突き止める作業が主になるが、遅延評価はそもそもユーザが意図したフローで動いていない場合が多いからだ。意図したフローで動いていなくても結果は同じというのが遅延評価の特徴なわけだが、制御フローのデバッグは結果より過程が重要になり、過程が突き止めにくいことは大きな障壁になる。例えば、トレースを安直に挿入すると、トレース結果が意図したものと逆の時系列が出る経験をしたことはないだろうか? これは、まあ慣れた Haskell プログラマなら、どういう場所に挿入したか想像がつくと思うが、個人的には一回はギョッとする奴だと思ってる。こういうトレース場所をよく考えて挿入しなきゃいけないというのは、結構不安を呼ぶ。トレースがちゃんとでない場合、それは制御フローがバグってるのか、自分が浅はかで評価フロー的に大事なポイントにトレースがちゃんと挿入できていないのかが一見して分からないからだ。</p>
<p>ところで、GHC 8.0 から <tt class="docutils literal">Strict</tt> 拡張が追加された。これはとりあえずあらゆるところで bang pattern を付け、コンストラクタのフィールドも全部正格フラグをつけるというやつで、ちょっと厄介ポイントはあるものの、不安は結構解消される。僕は、最近この拡張デフォルト有効でプログラムを書いていて、正直 <tt class="docutils literal">Strict</tt> 拡張ない頃には戻りたくないですね。なお、この拡張はパフォーマンス解析にも役に立つ。その理由はここで挙げた点と同じで、やはり評価フローが大体自分が意図した通りというのは大事という感じ。</p>
</div>
<div class="section" id="auto-id-9">
<h2>問題3: ちゃんと機能しないベンチマーク<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>以下のようなプログラムを考える:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">BinTree</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Node</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="p">(</span><span class="kt">BinTree</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">BinTree</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Leaf</span><span class="w"> </span><span class="n">a</span>
<span class="nf">findRightOdd</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">BinTree</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Maybe</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">findRightOdd</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">Leaf</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">maybeOdd</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">Node</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">lt</span><span class="w"> </span><span class="n">rt</span><span class="p">)</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">rt</span>
<span class="w"> </span><span class="o"><|></span><span class="w"> </span><span class="n">maybeOdd</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="o"><|></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">lt</span>
<span class="w"> </span><span class="n">maybeOdd</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">`</span><span class="n">mod</span><span class="p">`</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Nothing</span>
</pre></div></td></tr></table></div>
<p>なんて事のないプログラムで、数値を値に持つ二分木が与えられた場合に、一番右側にある奇数の値を取得するプログラムになる。さて、このプログラムは奇数が見つかればそこで木の探索を終了するはずなので、奇数が早めに見つかる場合は、全部探索して奇数を見つけるプログラムより速いはずだ。そこで、</p>
<ol class="arabic simple">
<li>一番右側に奇数がある木</li>
<li>奇数がない木</li>
<li>ランダムに値を埋め込んだ木</li>
</ol>
<p>を作って、プログラムの速度を実測してみたところ、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≪</mo><mn>3</mn><mo>≪</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">1 \ll 3 \ll 2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≪</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">3</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≪</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span></span></span></span></span> を期待したのに、<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≪</mo><mn>2</mn><mo>≪</mo><mn>3</mn></mrow><annotation encoding="application/x-tex">1 \ll 2 \ll 3</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≪</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≪</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">3</span></span></span></span></span> という結果が得られた。一体上の簡単なプログラムのどこに間違いがあったんだろう? 実測に使ったプログラムは、<a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2020/03/haskell-lazy-debug-problem/haskell-lazy-debug-problem/Problem03.html">Problem03.hs</a> になる。このプログラムに間違いがあれば指摘して欲しい。</p>
<p>この問題の修正例は、<a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2020/03/haskell-lazy-debug-problem/haskell-lazy-debug-problem/Problem03A.html">Problem03A.hs</a> になる。</p>
<p>最後は、疲れちゃったので、易しい問題で。修正の仕方は色々考えられると思う。作者自身は、ちゃんとベンチマークしたいわけじゃなくて、プログラムが意図通り動いていそうか軽く確認したいというのがポイントだ。さて、デフォルト遅延評価でのパフォーマンス予測は常に厄介で、大体外れる (個人の感想です)。この原因は、主にパフォーマンスの問題が各関数で完結しておらず、相互作用によって決まる傾向にあるというのも大きいと思う。なので、Haskell でない言語でもイテレータやジェネレータを扱う場合のパフォーマンス解析は結構しんどい。ただ、そういう言語でも相互作用に決まるものと決まらないものはちゃんと区別されている。Haskell では区別されていない。これが一番きつい。これは、問題2でも共通だが、どこを疑えばいいのかが得られたデータからは判別しづらいからだと思う。なので、判別には経験が試される。</p>
<p>今回の場合、直接 <tt class="docutils literal">Strict</tt> 拡張が役に立つわけではないが、<tt class="docutils literal">Strict</tt> 拡張を使う事自体は判断の助けになるだろう。実はこのプログラムは、後輩が詰まっていた問題から着想を得ているんだけど、Haskell の経験が特にない人が Haskell を使って何かする必要に迫られ、しかもそれがパフォーマンスに関係する事である場合、まずは <tt class="docutils literal">Strict</tt> 拡張を有効にする事をお勧めする。これは速くなるとかではなくて、単にパフォーマンス解析のしやすさからだ。後、Haskell では、何の気なしに結構遅延評価を使っている場合が多く、しかも案外ネック部分に知らない間に適用されており、<tt class="docutils literal">Strict</tt> 拡張を有効にすると (アルゴリズムを変える必要があるレベルの) 大規模な改修が必要になったりする。そういう場面に気づくためにも、<tt class="docutils literal">Strict</tt> 拡張は使っておいた方がいい。その結果、遅延評価の機能が使いたくなったら、lazy pattern なり lazy flag なりで使えば良いと思う。ただ、デフォルトは <tt class="docutils literal">Strict</tt> 拡張有効の方が、変なところでつまづく確率が下がると思う。</p>
</div>
<div class="section" id="auto-id-10">
<h2>まとめ<a class="headerlink" href="#auto-id-10" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ということで、個人的に遅延評価で苦しい奴を3個ほど例示してみた。個人的には、最初に言った通り、</p>
<ul class="simple">
<li>プログラム自体が大きくて</li>
<li>複雑な制御構造をしていて</li>
<li><dl class="first docutils">
<dt>(optional) 以下のいずれかの条件を満たす</dt>
<dd><ul class="first last">
<li>遅延評価を機能として使っている</li>
<li>デバッグ対象が効率に関するバグである</li>
</ul>
</dd>
</dl>
</li>
</ul>
<p>なプログラムにおいて、デフォルト遅延評価によるデバッグはかなり辛いと思っている。問題1は遅延評価を機能として使っている例、問題3は効率に関するバグの例になる。もっとそれぞれの例を洗練して、ちゃんと議論しやすい土壌に持ってくのが良いとは思ってる。思ってるが、正直苦心してそういう例を考えたくないほど遅延評価辛いので、誰かよろしくって感じ。後、こういう問題には、こう対処すると良いみたいなんがあれば、是非教えて欲しい。</p>
<p>GHC の抽象機械や GC 自体は遅延評価を想定してる面があるし、遅延評価由来の最適化も結構色々あって面白いとは思う。おそらく Haskell がデフォルト遅延評価を選んでいなければ、ここまでの発展はなかったんじゃないだろうか。それを考えると、技術的には面白いとは思うんだけど、如何せんプログラミングユーザとしては辛すぎるので、僕は遅延評価捨てて欲しいです。よろしくお願いします。</p>
<table class="docutils footnote" frame="void" id="simple-example" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>最初シンプルな例を挙げよという話だったんだけど、基本的にはそれは前提が間違ってると思っていて、遅延評価は積もり積もるとデバッグの難易度が上がりやすいと思ってる。これは、正格評価でも同じではないかという話はあると思うけど、遅延評価の方が特定に時間がかかる上、余計なところに時間が取られやすいと思っている (定量的な話は出来ないけど。そもそも定量的な話ができるなら、ブログに書かないと言う話がある)。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="hutton-1998" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[2]</a></td><td>Hutton, G., & Meijer, E. (1998). Monadic parsing in Haskell. Journal of Functional Programming, 8(4), 437–444. <a class="reference external" href="https://doi.org/10.1017/S0956796898003050">https://doi.org/10.1017/S0956796898003050</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="hutton-1996" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[3]</a></td><td>Hutton, G., & Meijer, E. (1996). Monadic Parser Combinators. Retrieved from <a class="reference external" href="http://eprints.nottingham.ac.uk/237/">http://eprints.nottingham.ac.uk/237/</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-hutton-meijer-performance" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[4]</a></td><td>なお、Hutton & Meijer のパーサは、遅いしメモリも食うしみたいな事が知られている。で、普通はリストを捨てて継続を使ったり、先読みやエラー情報の保持を工夫したりする。もし、あなたが自身のプログラムでパーサコンビネータを使いたかったら、そのような工夫がされている Megaparsec / Attoparsec などを使うことをお勧めする。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-problem-hardness" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[5]</a></td><td>難易度が緩めになってるのは、まず難易度が高めの問題を僕がデバッグしたくないのと、そこまで時間をかけたくなかったというのがある。</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-problem-hardness-2" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-8">[6]</a></td><td>なお、実は故意に含んだバグと安直に実装したら埋め込まれたバグがある。</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/03/haskell-lazy-debug-problem.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/03/haskell-lazy-debug-problem.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>型クラスの Coherence と Orphan Instance2020-03-20T11:43:29+09:002020-03-29T09:49:38+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-03-20:/blog/posts/2020/03/coherent-typeclass-and-orphan-instance/<p>Haskell には型クラスと呼ばれる重要な機能がある.これは名前の通り,型をクラス分けするための機能で,その型に対して …</p><p>Haskell には型クラスと呼ばれる重要な機能がある.これは名前の通り,型をクラス分けするための機能で,その型に対してある操作が構成できることをその型の性質とみなし,性質に名前がつけられる機能だ.この機能は,アドホック多相,つまりは型による静的なオーバーロードを実現する仕組みとしての側面もある.型クラスに対しては,型ごとにそのインスタンス,つまり操作の実装を与えることができ,ある型がある型クラスに所属していることを型注釈で表明することができる.その表明は,コンパイラによるインスタンスの自動検索で解決され,解決できなかった場合は型エラーになる.</p>
<p>さて,型クラスの仕組みは coherence という,かなり強い性質を要求する.今回は,この coherence がどういう役割を持つかを,Haskell を例に見ていく.また,orphan インスタンスと呼ばれる特殊なインスタンスと coherence の関係性について言及する.</p>
<div class="section" id="auto-id-1">
<h2>型クラス<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>型クラスとは,その名の通り型のクラスのことだ.例えば,ある型 <tt class="docutils literal">A</tt> の全ての要素同士について等価性が判定可能なことは,Haskell では以下のように表明できる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">instance</span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kr">where</span><span class="w"> </span><span class="o">...</span>
</pre></div></td></tr></table></div>
<p>これは,型 <tt class="docutils literal">A</tt> が <tt class="docutils literal">Eq</tt> 型クラスに所属するということを表す.<tt class="docutils literal">Eq</tt> 型クラスは,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o">==</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
</pre></div></td></tr></table></div>
<p>のように書け,<tt class="docutils literal">A</tt> が二分木構造を持つデータとすると,上記の表明の完成形は,以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Leaf</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Node</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kt">A</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o">==</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="p">(</span><span class="kt">Leaf</span><span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="kt">Leaf</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">True</span>
<span class="w"> </span><span class="p">(</span><span class="kt">Leaf</span><span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="p">(</span><span class="kr">_</span><span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="kt">Leaf</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="p">(</span><span class="kt">Node</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">x2</span><span class="p">,</span><span class="w"> </span><span class="kt">Node</span><span class="w"> </span><span class="n">y1</span><span class="w"> </span><span class="n">y2</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">y1</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="n">y2</span>
</pre></div></td></tr></table></div>
<p>つまり,等価性判定の方法を具体的に与えることで,等価性判定可能であることを保証するわけだ.ところで,この仕組みは,型ごとのオーバーロードと見なすこともできる.Haskell での利用は多くの場合,後者の役割が期待されている場合が多い.上記の例では,様々な型でそれぞれ異なる等価性判定を <tt class="docutils literal"><span class="pre">(==)</span></tt> という同じ名前の演算子で参照できる.例えば,以下のようにだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Eq</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">f</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">z</span>
</pre></div></td></tr></table></div>
<p>型クラスで導入された操作をメソッドと呼び,メソッドはそれぞれ型制約のついた関数として参照できる.例えば,<tt class="docutils literal"><span class="pre">(==)</span></tt> は,<tt class="docutils literal"><span class="pre">(==)</span> :: Eq a => a <span class="pre">-></span> a <span class="pre">-></span> Bool</tt> という型を持つ演算子として参照できる.型制約を持つ型は,その検査の際型制約に関する保証,つまりスコープ内に何らかのインスタンスが必ずあることを求める.<tt class="docutils literal">f</tt> 内での <tt class="docutils literal"><span class="pre">(==)</span></tt> の呼び出しは,<tt class="docutils literal">f</tt> の型制約によって <tt class="docutils literal">Eq a</tt> というインスタンスがあることが保証されるため,問題なく使用できるが,<tt class="docutils literal">f :: a <span class="pre">-></span> a <span class="pre">-></span> a <span class="pre">-></span> Bool</tt> のような型にすると型エラーになる.ただ,保証は呼び出し元の型制約だけによるものではない.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">g</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">z</span>
</pre></div></td></tr></table></div>
<p>と書いた場合,<tt class="docutils literal">g</tt> は特に型制約を必要としない.この場合,<tt class="docutils literal">A</tt> に関するインスタンスがあることから,直接保証が得られる.Haskell の型クラスの仕組みの面白い点は,インスタンスの解決方法と型推論の方法さえ与えられれば,型クラスを持たない言語に elaboration するだけ <a class="footnote-reference" href="#notice-rankntypes" id="auto-id-2">[1]</a> で実行の意味論を与えられる点だ.この方法は辞書渡しという名前で知られていて,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">C</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">m1</span>
</pre></div></td></tr></table></div>
<p>というようなプログラムを,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">DictC</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DictC</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">instDictC_A</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">DictC</span><span class="w"> </span><span class="kt">A</span>
<span class="nf">instDictC_A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DictC</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">DictC</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="n">d</span>
</pre></div></td></tr></table></div>
<p>というように,型クラスに対応する辞書と呼ばれるデータ型を作り,その型の値を明示的に渡していくことで実現される.GHC では,この elaboration による実行時表現をそのまま採用しており,内部は辞書渡しにより実現されている.</p>
</div>
<div class="section" id="coherence">
<h2>型クラスの Coherence<a class="headerlink" href="#coherence" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ところで,Haskell の型クラスのインスタンスには,以下のような制約がある.</p>
<blockquote>
<p>A type may not be declared as an instance of a particular class more than once in the program.</p>
<p>プログラム中において,特定のクラスに対し,ある型をそのインスタンスとして一度より多く (複数回) 定義することはできません.</p>
<p class="attribution">—<a class="reference external" href="https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-770004.3.2">Haskell Language Report 4.3.2 Instance Declarations</a></p>
</blockquote>
<p>この制限は時折物議を醸すわけで,実際この制限を緩和する GHC の言語拡張も幾つか存在する.しかし,言語拡張でも完全にこの制限が取り払えるわけでは無い.では,具体的に何が問題になるかを考えてみる.次のようなプログラムを考えてみよう:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">C1</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">C1</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">C2</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">C2</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m2</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">C1</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">C2</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m2</span><span class="w"> </span><span class="n">m1</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">f</span>
</pre></div></td></tr></table></div>
<p>このプログラムでは,型クラスの継承が行われている.継承とは,型があるクラスに所属している場合にのみ,そのクラスのインスタンスを定義できるという制約をかける機能で,いわばある型クラスの部分クラスを定義できる機能だ.この場合の elaboration によって得られるプログラムは,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">DictC1</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DictC1</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">}</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">DictC2</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DictC2</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">superC1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">DictC1</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">m2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">instDictC1_Int</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">DictC1</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">instDictC1_Int</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DictC1</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">instDictC2_Int</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">DictC2</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">instDictC2_Int</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DictC2</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">superC1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">instDictC1_Int</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">m2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">DictC1</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">DictC2</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">f</span><span class="w"> </span><span class="n">d1</span><span class="w"> </span><span class="n">d2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m2</span><span class="w"> </span><span class="n">d2</span><span class="w"> </span><span class="p">(</span><span class="n">m1</span><span class="w"> </span><span class="n">d1</span><span class="p">)</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">instDictC1_Int</span><span class="w"> </span><span class="n">instDictC2_Int</span>
</pre></div></td></tr></table></div>
<p>のように elaboration される.そうとは限らなくね?と思った人は正しくて,実は elaboration はもう一つやり方がある.それは次の部分を変えるやり方だ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="w"> </span> f :: DictC1 a -> DictC2 a -> a
<span class="gd">- f d1 d2 = m2 d2 (m1 d1)</span>
<span class="gi">+ f _ d2 = m2 d2 (m1 d1) where</span>
<span class="gi">+ d1 = superC1 d2</span>
</pre></div></td></tr></table></div>
<p>関数 <tt class="docutils literal">f</tt> における制約から <tt class="docutils literal">C1 a</tt> のインスタンスを保証する方法は,制約中の <tt class="docutils literal">C1 a</tt> から直接保証する方法と,<tt class="docutils literal">C2 a</tt> からその上位クラスが <tt class="docutils literal">C1 a</tt> であることを導きそこから保証する方法の2通りあり,前者が最初に示した方法,後者がその次に示した方法ということになる.ところで,この2通りの elaboration について,もし <tt class="docutils literal">Int</tt> の <tt class="docutils literal">C1</tt> に対するインスタンスが複数定義できた場合を考えてみる.この場合,elaboration において <tt class="docutils literal">DictC2</tt> の <tt class="docutils literal">superC1</tt> にその内の1つが入り,<tt class="docutils literal">g</tt> の呼び出し時に <tt class="docutils literal">f</tt> に渡す <tt class="docutils literal">DictC1 a</tt> の値は別のものが入ると,2通り示した elaboration の方法のどちらを採用するかによって,<tt class="docutils literal">g</tt> の結果が変わる可能性がある.</p>
<p>また,もう1つ別の例を見てみよう:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">h</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Int</span><span class="p">,</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span>
<span class="nf">h</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">m1</span><span class="p">,</span><span class="w"> </span><span class="n">m1</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>この例は次のように elaboration される:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">h</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Int</span><span class="p">,</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span>
<span class="nf">h</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">m1</span><span class="w"> </span><span class="n">instDictC1_Int</span><span class="p">,</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="n">instDictC1_Int</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>さて,この例は,<tt class="docutils literal">Int</tt> に対する <tt class="docutils literal">C1</tt> のインスタンスの定義が1つだから,何も考えずに <tt class="docutils literal">instDictC1_Int</tt> を渡すことができているわけだ.しかし,インスタンスが複数あった場合は,もちろん次のような elaboration があり得るかもしれない:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">h</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Int</span><span class="p">,</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span>
<span class="nf">h</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">m1</span><span class="w"> </span><span class="n">instDictC1_Int</span><span class="p">,</span><span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="n">instDictC1_Int'</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>つまり,それぞれ異なるインスタンスが適用されるわけだ.この例だとあまり問題に対して直感的では無いかもしれないが,例えば等価性をあるプログラムで2回使った場合,等価性のためのインスタンスが2種類あった場合,最初の使用と2回目の使用で異なる等価性のアルゴリズムが動くということがあり得るということだ.これは,多くの人にとってあまり嬉しい仕様では無いだろう.この例は先ほどの例に比べたら些細な例だと思えるかもしれない.多くの場合インスタンス解決のアルゴリズムが,このような狭いスコープで異なるインスタンスを選ぶことはまずない <a class="footnote-reference" href="#notice-mean-instance-resolution" id="auto-id-3">[2]</a>.ただ,次のような状況を考えてみるとどうだろう?</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">instance</span><span class="w"> </span><span class="kt">C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="nf">h1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">h1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m1</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">C1</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">m1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">1</span>
<span class="nf">h2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Int</span><span class="p">,</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span>
<span class="nf">h2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">m1</span><span class="p">,</span><span class="w"> </span><span class="n">h1</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>この場合,<tt class="docutils literal">h1</tt> での <tt class="docutils literal">m1</tt> と,<tt class="docutils literal">h2</tt> での <tt class="docutils literal">m1</tt> で異なるインスタンスを使う可能性は十分ありうる.これを是とするかどうかは,おそらく意見の分かれるところだと思う.ただ,Haskell では equational reasoning に基づく変形が好まれるため,<tt class="docutils literal">h1</tt> を直接 <tt class="docutils literal">m1</tt> に置き換える変形ができないことは,1つの問題点となりうる.</p>
<p>一般に,型クラスのインスタンス解決は型システムに組み込まれることが多い.その場合,型検査の際インスタンス解決が行われる.そして,型検査において作られた型の導出木に対する変換により elaboration が行われる.このような変換の枠組みは,型クラス以外でも採用されることがある.具体的には,暗黙の型変換やレコード型などだ.そして,それらの場合にも上記で挙げた複数のインスタンスがある場合に起こる問題と似たような問題が起こることがある.この問題は,次のように形式化される:</p>
<blockquote>
型の導出木から言語への変換があった時,ある型の異なる2つの導出木において,変換を行った結果が意味論同値にならない.</blockquote>
<p>例えば,<tt class="docutils literal">h</tt> の例では2つの <tt class="docutils literal">m1</tt> に対してそれぞれ同じインスタンスを使っても異なるインスタンスを使っても,どんなインスタンスを使っても,それが <tt class="docutils literal">Int</tt> に対する <tt class="docutils literal">C1</tt> のインスタンスであれば型検査は通るのが一般的だ.しかし,その場合使ったインスタンスに対する elaboration した結果は,他のインスタンス解決を行ってから elaboration した結果と振る舞いが変わる場合がある.逆にこのような問題がなければ,型システムに対して一定の保証が与えられる.この保証,つまり上記で形式化した問題が成り立たない型システムと elaboration の性質のことを,一般に coherence と呼ぶ <a class="footnote-reference" href="#tapl-subtyping-coherence" id="auto-id-4">[3]</a>.coherence を保証する方法論は幾つかあるが,Haskell では型クラスのインスタンスを1つしか定義できないようにすることで,coherence を保証している <a class="footnote-reference" href="#incoherent-type-class" id="auto-id-5">[4]</a>.</p>
</div>
<div class="section" id="orphan">
<h2>orphan インスタンス<a class="headerlink" href="#orphan" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,Haskell では coherence を保証するため,型クラスのインスタンスは型に対して1つしか定義できないようにしている.ところで,この「型クラスのインスタンスは型に対して1つしか定義できないようにする」というのは,言うだけなら単純に見えるが,幾つかの課題もある.特に著名な問題が,orphan インスタンスである.GHC では,ある型 <tt class="docutils literal">T</tt> の <tt class="docutils literal">C</tt> のインスタンス宣言において,その宣言が <tt class="docutils literal">T</tt> の宣言または <tt class="docutils literal">C</tt> の宣言と同じモジュールにあるかないかで,インスタンスに関する扱いが変わる.特に同じモジュールにない場合は,orphan インスタンスと呼ばれ,警告が表示されるようになっている.なぜこのような区分があるのだろうか?</p>
<p>まず,Haskell ではインスタンスが暗黙的にモジュール間を伝搬する.これは,以下のように規定されている:</p>
<blockquote>
<p>All instances in scope within a module are always exported and any import brings all instances in from the imported module. Thus, an instance declaration is in scope if and only if a chain of import declarations leads to the module containing the instance declaration.</p>
<p>モジュールにおいて,スコープ内の全てのインスタンスは常にエクスポートされ,任意の <tt class="docutils literal">import</tt> は,インポートしたモジュールから全てのインスタンスを取り込みます.したがって,インスタンス宣言がスコープ内にあるということは,<tt class="docutils literal">import</tt> 宣言のチェインがそのインスタンス宣言を含むモジュールにたどり着くということと同値です.</p>
<p class="attribution">—<a class="reference external" href="https://www.haskell.org/onlinereport/haskell2010/haskellch5.html#x11-1060005.4">Haskell Language Report 5.4 Importing and Exporting Instance Declarations</a></p>
</blockquote>
<p>私たちにこの伝搬を止めることはできないし,制御することもできない.これは,そもそもプログラム中でインスタンスは型に対して1つしか定義できないため制御する必要が特に生じないからだ <a class="footnote-reference" href="#consider-coherence-for-instance-leading" id="auto-id-6">[5]</a>.ところで,こういう規定があるのはいいとして,実際問題として Haskell のコンパイラは,インスタンスの解決をこの規定に従って行わなければならない.もちろん,どのモジュールにインスタンスがあるか分からないため,最悪全てのモジュールを調べる必要がある.ユーザ側にとってもこの規定は問題だ.もし,重要な2つのモジュールがそれぞれある型に対しての別々のインスタンス定義を保有している場合,それらのモジュールが <tt class="docutils literal">import</tt> チェインに入ってる全てのモジュールがインスタンスの競合により使用できなくなる.</p>
<p>ところで,ある型のあるクラスのインスタンスを使用する場合,その型とクラスに関する情報が無いとどうしようもないので,それぞれの宣言があるモジュールの情報は必ず見に行くことになる.そして,第三者がそのモジュールをいじると言うことは起こり得ない.つまり,そのいずれかのモジュールにインスタンス宣言が含まれているなら,コンパイラにとって必要な情報を見るついでにインスタンスも見れ,またユーザ側にとってももしインスタンス競合が起こったならそもそもその型やクラスを読み込めないことになるため,逆に型やクラスが読み込めればインスタンス競合がないことが保証でき嬉しい.そこで,Haskell ではある型のあるクラスに対するインスタンス宣言は,その型またはクラス宣言と同じモジュールに置くことが推奨されている.逆に独立したモジュールにあるインスタンスは orphan インスタンスと呼ばれ,なるべく控えるように勧告されている.そのため,ある型に対して独立にインスタンスが作りたい場合,<tt class="docutils literal">newtype</tt> によって新たにインスタンスの意味論だけを変える型を作り,その型に対するインスタンス宣言を行うということが行われている.</p>
<p>なお,GHC では,orphan インスタンスがあるモジュールは内部でマークされていて,モジュールのインターフェースファイルにはそのモジュールが依存する orphan インスタンスのあるモジュールが列挙されている.そして,コンパイル時にそのリストにあるモジュールの全てのインターフェースファイルを読みに行くようになっている.よって,一旦 orphan インスタンスを作ってしまうと,そのインスタンスがあるモジュールのインターフェースファイルは,そのモジュールに依存する全てのモジュールが再コンパイルされる際,どのような変更だろうと読み込まれることになる.よって,orphan インスタンスはコンパイル時間にも悪影響を与える <a class="footnote-reference" href="#notice-orphan-instance-compiling" id="auto-id-7">[6]</a>.</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,型クラスのコヒーレンスと orphan インスタンスの関係性について紹介した.一応,インスタンスが型に対して1つしか作れないのと,インスタンスが暗黙に伝搬してしまうのには理由があるんだよと言う話でした.最近 Haskell のフォークみたいな言語を作ろうとしてて,そういやこの辺まとまった記事ないなあと思って書いた.ezyang 先生の <a class="reference external" href="http://blog.ezyang.com/2014/07/type-classes-confluence-coherence-global-uniqueness/">Type classes: confluence, coherence and global uniqueness</a> はよくまとまってるので,この辺もよかったら参照すると良さそう.</p>
<p>なお,別の話題として型クラスの elaboration って要は暗黙的な引数の elaboration と見做せるよねと言う話題が古くからある.ただ,暗黙的引数とみるからには明示的に適用したくなるわけで,その辺の機能を入れた場合に coherence をどう考えるかという話題があったりする.この辺は一昨年の Haskell Symposium で <a class="reference external" href="https://dl.acm.org/doi/10.1145/3299711.3242752">Coherent explicit dictionary application for Haskell</a> というセッションがあったりする.この辺も近いうちに紹介できたらなと思う (思ってるだけ).</p>
<table class="docutils footnote" frame="void" id="notice-rankntypes" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>なお,素の Haskell には落とせなくて,ランク2多相ぐらいが必要になる.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-mean-instance-resolution" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[2]</a></td><td>もちろん故意にそのようなアルゴリズムを作る場合は別だが.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="tapl-subtyping-coherence" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[3]</a></td><td>みんな読んでる TaPL では,15.6 で触れられてるっぽい.ここでは,subtyping を例にとってる.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="incoherent-type-class" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[4]</a></td><td>ところで,GHC では <tt class="docutils literal">INCOHERENT</tt> プラグマというものが用意されており,名前の通り coherence を捨てる代わりに複数のインスタンス定義をできるようにするプラグマだ.当然の帰結ながら,GHC ユーザの間ではあまり使わないほうがいいプラグマとして扱われている.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="consider-coherence-for-instance-leading" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[5]</a></td><td>と言ってみたものの,制御する方はそれでいいとして,伝搬を止める方は実は問題があるのかよく分かってない.coherence が成り立たなくなるような気が直感的にするんだけど,インスタンスが消えるということは,型の導出がそもそもできない気がしていて,それは大丈夫そうな気もする? ただ,equational reasoning による変形がモジュール跨ぐとできなくなる場合が生じるという点では問題.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-orphan-instance-compiling" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[6]</a></td><td>と言っても他の要素に比較すればそれほど大した時間ではないが.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/03/coherent-typeclass-and-orphan-instance.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/03/coherent-typeclass-and-orphan-instance.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>LaTeX の数式フォントに STIX を使う2020-03-07T05:59:35+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-03-07:/blog/posts/2020/03/latex-with-stix-font/<p>LaTeX では Computer Modern フォントが使われている.ただ,Computer Modern フォントはかなり古く対応してる文字もあまり多くない.特に日本語 …</p><p>LaTeX では Computer Modern フォントが使われている.ただ,Computer Modern フォントはかなり古く対応してる文字もあまり多くない.特に日本語環境だと IPA フォントなどと併用して使われることが多い.僕自身は Computer Modern に代わる目的で作られた Latin Modern フォントと IPA フォントを使ってきたんだけど,最近数式環境だけ STIX フォントに切り替えた.そのメモ.</p>
<div class="section" id="auto-id-1">
<h2>きっかけ<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>クラス <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>⊊</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">A \subsetneq B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⊊</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> またはその逆か,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>=</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">A = B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> か,互いに比較不能,つまり <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>⊈</mo><mi>B</mi><mo>∧</mo><mi>B</mi><mo>⊈</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">A \nsubseteq B \land B \nsubseteq A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0966em;vertical-align:-0.3027em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⊈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0966em;vertical-align:-0.3027em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⊈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> かの何の関係であるかは重要になることが多い.ところで,比較不能に関してだけ2項演算ではないわけだけど,これを他と合わせて書く表記はないのだろうかというと,一応あって「⫓」を否定する記号が使われる.「⫓」の意味としては部分集合であり上位集合であるという意味になっていて,それを否定するのでそのどちらでもない,つまり片方だけに含まれる要素がそれぞれ存在するということになる.ただこの記号,LaTeX の標準パッケージ中ではサポートされていない.ところで,この記号は Unicode では U+2AD3 の文字としてサポートされていて,この文章でも Unicode 文字をそのまま使っている.</p>
<p>まあ,とてつもなくこの文字が出したいというわけではないんだけど,どうせだったので Unicode 対応フォントを使えないのかなということで探して見つけたのが,STIX フォントになる.それまでは Latin Modern フォントと <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo></mrow><annotation encoding="application/x-tex">\llbracket</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">\rrbracket</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span> を出すために <tt class="docutils literal">stmaryrd</tt> というパッケージを合わせて使ってたんだけど,これも Unicode に含まれてるので STIX フォントに切り替えれば書かずにすむようになる.<tt class="docutils literal">stmaryrd</tt> はそもそも独自のフォントを提供してたのだけど,bold font に対応してないなどの問題点もあった.STIX フォントに切り替えればそういう問題も解決するし,フォント管理も一括でできるようになりそうという感じ.</p>
<p>STIX フォントと Latin Modern の違いは以下の感じ <a class="footnote-reference" href="#license-notice" id="auto-id-2">[1]</a>:</p>
<dl class="docutils">
<dt>Latin Modern フォント</dt>
<dd><img alt="Latin Modern フォントによる数式サンプル" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2020/03/latex-with-stix-font/latex-with-stix-font/latin-modern-sample.png"/>
</dd>
<dt>STIX フォント</dt>
<dd><img alt="STIX フォントによる数式サンプル" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2020/03/latex-with-stix-font/latex-with-stix-font/stix-sample.png"/>
</dd>
</dl>
<p>ちょっと,STIX フォントの方が太めになってるのと,不格好な部分はあるけど,許容範囲ではあるかなという感じ.とりあえず,今のところ使ってて不便に感じる点はないけど,将来的には差し戻す可能性もあるかも.それを試すためのお試し使用みたいな面もある.</p>
</div>
<div class="section" id="stix">
<h2>STIX フォントの導入<a class="headerlink" href="#stix" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>普段僕は <tt class="docutils literal">upLaTeX</tt> と <tt class="docutils literal">dvipdfmx</tt> を使ってる.その場合の STIX フォントの導入方法を書いておく.といってもそれほど難しくない.CTAN で STIX フォントの対応パッケージが提供されてるので,それをインストールして使うだけ.STIX フォントは,Type1 フォントと OpenType フォントどちらも提供されてて,好きな方使えばいい.Type1 フォントの方は <tt class="docutils literal"><span class="pre">stix2-type1</span></tt>,OpenType フォントの方は <tt class="docutils literal"><span class="pre">stix2-otf</span></tt> という名前で提供されてる.ここでは,Type1 フォントの方を使っていく.やることは,</p>
<ol class="arabic">
<li><p class="first">まず,<tt class="docutils literal"><span class="pre">stix2-type1</span></tt> パッケージをインストールする:</p>
<pre class="literal-block">
tlmgr install stix2-type1
</pre>
</li>
<li><p class="first"><tt class="docutils literal">\usepackage{stix2}</tt> する</p>
</li>
</ol>
<p>こんだけ.これをやると全てのフォントで STIX フォントが使われるようになるけど,数式だけに適用したかったら,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">\usepackage</span><span class="na">[notext]</span><span class="nb">{</span>stix2<span class="nb">}</span>
</pre></div></td></tr></table></div>
<p>とする.これでとりあえず大丈夫.</p>
</div>
<div class="section" id="auto-id-3">
<h2>通常使えない記号を使う<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal">stix2</tt> パッケージでは,フォントの設定の他に数式記号コマンドもいくつか提供してくれてる.詳しくは,<a class="reference external" href="http://mirrors.ctan.org/fonts/stix2-type1/stix2.pdf">ユーザマニュアル</a> の Math Symbols の節を読むと良い.例えば</p>
<ul class="simple">
<li>⫓ : <tt class="docutils literal">\subsup</tt></li>
<li>⟦ : <tt class="docutils literal">\lBrack</tt></li>
</ul>
<p>みたいな感じ.既に定義されてる記号は,そっちが優先されるようになってるので,そこんとこも調整されてる.後デフォルトで <tt class="docutils literal">textcomp</tt> パッケージを読むようになってて,それが嫌なら <tt class="docutils literal">notextcomp</tt> オプションをつけるといい.</p>
</div>
<div class="section" id="auto-id-5">
<h2>まとめ<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,Latin Modern + IPA + stmaryrd から文書は Latin Modern + IPA,数式は STIX みたいな構成に変えて最近は LaTeX を書いてる.そのうち文書の方も STIX + IPA にするかもという感じ.STIX よりこっちの方がおすすめみたいなのあれば教えて欲しいかも.というわけで,今回は以上.</p>
<table class="docutils footnote" frame="void" id="license-notice" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>Latin Modern は <a class="reference external" href="http://www.gust.org.pl/projects/e-foundry/licenses/GUST-FONT-LICENSE.txt/view">The GUST Font License (GFL)</a> ,STIX は <a class="reference external" href="https://github.com/stipub/stixfonts/blob/master/docs/STIX_2.0.2_release_notes.txt">The SIL Open Font License</a> で提供されている.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/03/latex-with-stix-font.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/03/latex-with-stix-font.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>AtCoder の新環境テストの問題を解いてみる2020-02-17T11:24:02+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-02-17:/blog/posts/2020/02/haskell-atcoder-template/<p>AtCoder が現在新環境のテストをしている: <a class="reference external" href="https://atcoder.jp/contests/language-test-202001">https://atcoder.jp/contests/language-test-202001</a></p>
<p>今までの環境では GHC 7.10.3 だったのが,新環境では 8.6.5 になるの …</p><p>AtCoder が現在新環境のテストをしている: <a class="reference external" href="https://atcoder.jp/contests/language-test-202001">https://atcoder.jp/contests/language-test-202001</a></p>
<p>今までの環境では GHC 7.10.3 だったのが,新環境では 8.6.5 になるので,この機会に参加してみるかということで,テストで公開されてる問題を解いてみた.そのコードと解説.なお,当方 AtCoder の Haskell 経験全然無いので,なんか指摘あったらしてくれ.</p>
<div class="section" id="auto-id-1">
<h2>テンプレ作成<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>よく知られてる問題として,Haskell で AtCoder の問題解く場合,<tt class="docutils literal">Prelude</tt> を単純に使うと全部 <tt class="docutils literal">String</tt> でデータを持ってきてしまいめっちゃメモリ食って GC のお世話になると言うのがある.他にも AtCoder の問題だと気軽にソートしたい時とかあるけど,リストのソートめっちゃ遅かったり,とにかく <tt class="docutils literal">Prelude</tt> はめっちゃリスト推してくるんだけど,現実的にリストだと辛い場面が多い.なので,<tt class="docutils literal">ByteString</tt> や <tt class="docutils literal">Vector</tt> 系の API を整備したくなってくるので,整備した.</p>
<p>整備したのは, <a class="reference external" href="https://github.com/mizunashi-mana/haskell-atcoder-template">https://github.com/mizunashi-mana/haskell-atcoder-template</a> に置いてある.もし,ちゃんと ARC / ABC に参加してたら,不足してるのどんどん足してくかもしれない.</p>
<p>具体的に何整備したかと言うと,まずよく使う言語拡張のオプション追加した:</p>
<dl class="docutils">
<dt><tt class="docutils literal">BangPatterns</tt></dt>
<dd>bang pattern <tt class="docutils literal">!</tt> が使えるようになる拡張.これつけるとパターンを一回 <tt class="docutils literal">seq</tt> 挟んでから照合するようになる.これ付けとくと,最適化の解析がちょっと速くなって,情報も増えるので通常より最適か効きやすくなって速くなる場合が多い.ただ,後述する <tt class="docutils literal">Strict</tt> で基本は付くのであまり使わなくて良い.ただ,ネストしたパターンについては,<tt class="docutils literal">Strict</tt> じゃダメな場合があるので,明示的に bang pattern 書く必要がある</dd>
<dt><tt class="docutils literal">BlockArguments</tt></dt>
<dd><tt class="docutils literal">f $ \x <span class="pre">-></span> x</tt> とかを <tt class="docutils literal">f \x <span class="pre">-></span> x</tt> って書けるやつ.いらない <tt class="docutils literal">$</tt> 省けるのでタイプ数が 1 減る</dd>
<dt><tt class="docutils literal">FlexibleContexts</tt></dt>
<dd>型制約の記法をちょっと柔軟にするやつ.普通 <tt class="docutils literal">f :: Enum Int => Int</tt> とか書けないところを書けるようにしてくれる.元々の制限は型推論で出てきた型にも適用されるので,<tt class="docutils literal">Vector</tt> の API とかでたまにこの拡張が必要になる</dd>
<dt><tt class="docutils literal">LambdaCase</tt></dt>
<dd><tt class="docutils literal">\x <span class="pre">-></span> case x of ...</tt> を <tt class="docutils literal">\case ...</tt> って書けるやつ.モナディックなやつ書くときに <tt class="docutils literal">do { r <- m; case r of ... }</tt> を <tt class="docutils literal">m >>= \case ...</tt> みたいに書ける</dd>
<dt><tt class="docutils literal">MultiWayIf</tt></dt>
<dd><p class="first"><tt class="docutils literal">if cond1 then e1 else if cond2 then e2 else e3</tt> を</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">if</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">cond1</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">e1</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">cond2</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">e2</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">e3</span>
</pre></div></td></tr></table></div>
<p class="last">って書けるやつ.ネストをしないで済みやすい</p>
</dd>
<dt><tt class="docutils literal">OverloadedLists</tt></dt>
<dd><tt class="docutils literal">[x :: a, y, z]</tt> が <tt class="docutils literal">(IsList l, Item l ~ a) => l</tt> みたいな型を持つようになるやつ. <tt class="docutils literal">Vector</tt> 気軽に作りたいとき便利</dd>
<dt><tt class="docutils literal">OverloadedStrings</tt></dt>
<dd><tt class="docutils literal">"str"</tt> が <tt class="docutils literal">IsString p => p</tt> みたいな型を持つようになるやつ. <tt class="docutils literal">ByteString</tt> 気軽に作りたいとき便利</dd>
<dt><tt class="docutils literal">ScopedTypeVariables</tt></dt>
<dd>トップレベルの型注釈で <tt class="docutils literal">forall a. a <span class="pre">-></span> a</tt> みたいな書き方ができるようになって,型 <tt class="docutils literal">a</tt> を式中で参照できるようになるやつ.後述の <tt class="docutils literal">TypeApplications</tt> と合わせて使うと便利</dd>
<dt><tt class="docutils literal">Strict</tt></dt>
<dd>全てのパターンの外側に bang pattern <tt class="docutils literal">!</tt> が付くようになるやつ.bang pattern いちいち付けても同じ恩恵受けられるけど,めんどいし忘れる場合も多いのでこの拡張使うと良い</dd>
<dt><tt class="docutils literal">TypeApplications</tt></dt>
<dd><tt class="docutils literal">x :: forall a b. a <span class="pre">-></span> Int <span class="pre">-></span> b</tt> みたいなのに対して,<tt class="docutils literal">x @Char @() :: Char <span class="pre">-></span> Int <span class="pre">-></span> ()</tt> みたいに型適用できるやつ. <tt class="docutils literal">read :: forall a. Read a => String <span class="pre">-></span> a</tt> 系の出力が多相的なやつは曖昧な型でエラーになりやすいが,<tt class="docutils literal">read @Int</tt> みたいにしておくとわざわざ注釈書かなくても型を決められる</dd>
</dl>
<p>それから入出力系を整備した.まず, <tt class="docutils literal">Read</tt> に変わるやつで, <tt class="docutils literal">ReadBS</tt> っていうの定義してる.これは単純に <tt class="docutils literal">ByteString</tt> から読み込むやつ.で,それベースに</p>
<dl class="docutils">
<dt><tt class="docutils literal">readLineInputs :: forall a. ReadBS a => IO [a]</tt></dt>
<dd>一行読み込んで,空白区切りで分けて,それぞれ読み込むやつ</dd>
<dt><tt class="docutils literal">readLineInputsVec :: forall a. ReadBS a => UVec.Unbox a => IO (Vector a)</tt></dt>
<dd><tt class="docutils literal">readLineInputs</tt> とやることは同じだけど,返り値がリストじゃなくて unboxed vector</dd>
<dt><tt class="docutils literal">discardLine :: IO ()</tt></dt>
<dd>一行捨てる</dd>
<dt><tt class="docutils literal">printN :: Show a => a <span class="pre">-></span> IO ()</tt></dt>
<dd>改行なし <tt class="docutils literal">print</tt></dd>
</dl>
<p>とかを定義した.後, <tt class="docutils literal">Vector</tt> / <tt class="docutils literal">MVector</tt> をそれぞれ unboxed vector / unboxed mutable vector のエイリアスに設定してたり,<tt class="docutils literal">Debug</tt> 空間を <tt class="docutils literal">Debug.Trace</tt> のエイリアスにしたり,諸々小細工したりしてる.詳細は <a class="reference external" href="https://github.com/mizunashi-mana/haskell-atcoder-template/blob/master/src/Header.hs">https://github.com/mizunashi-mana/haskell-atcoder-template/blob/master/src/Header.hs</a> を見てくれ.</p>
<p>で,こいつを <tt class="docutils literal">CPP</tt> で <tt class="docutils literal">#include</tt> して使ってる.</p>
</div>
<div class="section" id="language-test">
<h2>Language Test の解答例<a class="headerlink" href="#language-test" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>で,このテンプレを使った解答例を挙げていく.入出力の概略ぐらいしか問題文は書かないので,<a class="reference external" href="https://atcoder.jp/contests/language-test-202001/tasks">AtCoder の問題ページ</a> も参照してくれ.</p>
<div class="section" id="welcome-to-atcoder">
<h3>Welcome To AtCoder<a class="headerlink" href="#welcome-to-atcoder" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
a
b c
s
</pre>
<p class="last"><tt class="docutils literal">a</tt>,<tt class="docutils literal">b</tt>,<tt class="docutils literal">c</tt> は整数値,<tt class="docutils literal">s</tt> は文字列</p>
</dd>
<dt>出力</dt>
<dd><tt class="docutils literal">a + b + c</tt> と <tt class="docutils literal">s</tt> を空白区切りで一行に</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span><span class="w"> </span><span class="o">@</span><span class="kt">Int</span>
<span class="w"> </span><span class="p">[</span><span class="n">y</span><span class="p">,</span><span class="w"> </span><span class="n">z</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span><span class="w"> </span><span class="o">@</span><span class="kt">Int</span>
<span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">BS</span><span class="o">.</span><span class="n">getLine</span>
<span class="w"> </span><span class="n">printN</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">z</span>
<span class="w"> </span><span class="n">putSpace</span>
<span class="w"> </span><span class="kt">BS</span><span class="o">.</span><span class="n">putStrLn</span><span class="w"> </span><span class="n">s</span>
</pre></div></td></tr></table></div>
<p>これはいいと思う.type application が無いと,入力 <tt class="docutils literal">x</tt>,<tt class="docutils literal">y</tt>,<tt class="docutils literal">z</tt> が <tt class="docutils literal">Num a => a</tt> ぐらいまでしか決まらなくて,type defaulting が起きる.<tt class="docutils literal"><span class="pre">-Wall</span></tt> 下だと警告が出るので <tt class="docutils literal">Int</tt> を指定してる.</p>
</div>
<div class="section" id="product">
<h3>Product<a class="headerlink" href="#product" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
a b
</pre>
<p class="last"><tt class="docutils literal">a</tt>,<tt class="docutils literal">b</tt> は整数値</p>
</dd>
<dt>出力</dt>
<dd><tt class="docutils literal">a * b</tt> が奇数なら <tt class="docutils literal">Odd</tt> と,偶数なら <tt class="docutils literal">Even</tt> と出力</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="n">putStrLn</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">solve</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span>
<span class="nf">solve</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">String</span>
<span class="nf">solve</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">`</span><span class="n">mod</span><span class="p">`</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s">"Even"</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s">"Odd"</span>
</pre></div></td></tr></table></div>
<p>これも良いと思う.特に言うことはなさそう.</p>
</div>
<div class="section" id="placing-marbles">
<h3>Placing Marbles<a class="headerlink" href="#placing-marbles" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
abc
</pre>
<p class="last"><tt class="docutils literal">a</tt>,<tt class="docutils literal">b</tt>,<tt class="docutils literal">c</tt> は <tt class="docutils literal">0</tt> か <tt class="docutils literal">1</tt></p>
</dd>
<dt>出力</dt>
<dd><tt class="docutils literal">1</tt> の個数</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">Text</span><span class="o">.</span><span class="n">getLine</span>
<span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">ocount</span><span class="w"> </span><span class="p">(</span><span class="o">==</span><span class="w"> </span><span class="sc">'1'</span><span class="p">)</span><span class="w"> </span><span class="n">s</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">ocount :: MonoFoldable mono => (Element mono <span class="pre">-></span> Bool) <span class="pre">-></span> mono <span class="pre">-></span> Int</tt> は <tt class="docutils literal">ofoldl'</tt> で該当する要素を数える関数.微妙になかったので作った.</p>
</div>
<div class="section" id="shift-only">
<h3>Shift only<a class="headerlink" href="#shift-only" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
N
a1 ... aN
</pre>
<p class="last"><tt class="docutils literal">N</tt> は整数で,<tt class="docutils literal">a1</tt> から <tt class="docutils literal">aN</tt> も整数</p>
</dd>
<dt>出力</dt>
<dd>最大何回 <tt class="docutils literal">a1</tt> から <tt class="docutils literal">aN</tt> を 2 で割れるか</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">discardLine</span>
<span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">minimum</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="n">checkShifts</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="p">]</span>
<span class="c1">-- |</span>
<span class="c1">--</span>
<span class="c1">-- >>> checkShifts 0</span>
<span class="c1">-- 0</span>
<span class="c1">-- >>> checkShifts 2</span>
<span class="c1">-- 1</span>
<span class="c1">-- >>> checkShifts 20</span>
<span class="c1">-- 2</span>
<span class="c1">--</span>
<span class="nf">checkShifts</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">checkShifts</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">n</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">.&.</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">`</span><span class="n">shiftR</span><span class="p">`</span><span class="w"> </span><span class="mi">1</span>
</pre></div></td></tr></table></div>
<p>テンプレでは <tt class="docutils literal">Data.Bit</tt> が読み込まれてて使える.それ使って,それぞれ実際割り切れなくなるまで割ってみて,その中で一番早く割り切れなくなったやつを持ってくる.まあ,アルゴリズム的な最適化の余地は幾つかあるけど,いいでしょ.</p>
</div>
<div class="section" id="coins">
<h3>Coins<a class="headerlink" href="#coins" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
a
b
c
x
</pre>
<p class="last"><tt class="docutils literal">a</tt>,<tt class="docutils literal">b</tt>,<tt class="docutils literal">c</tt>,<tt class="docutils literal">x</tt> は整数</p>
</dd>
<dt>出力</dt>
<dd>500 が <tt class="docutils literal">a</tt> 個,100 が <tt class="docutils literal">b</tt> 個,50 が <tt class="docutils literal">c</tt> 個ある状況で,ちょうど <tt class="docutils literal">x</tt> になるような組み合わせの数</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="p">[</span><span class="n">b</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="p">[</span><span class="n">c</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="p">[</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">solve</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">x</span>
<span class="c1">-- |</span>
<span class="c1">--</span>
<span class="c1">-- >>> solve 1 1 1 0</span>
<span class="c1">-- 1</span>
<span class="c1">--</span>
<span class="nf">solve</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">solve</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">length</span><span class="w"> </span><span class="o">@</span><span class="kt">[]</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">a'</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="n">a</span><span class="p">]</span>
<span class="w"> </span><span class="n">b'</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="n">b</span><span class="p">]</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">x'</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">a'</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">500</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">b'</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">100</span>
<span class="w"> </span><span class="n">withFilter</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">x'</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="n">x'</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">50</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">withFilter</tt> は Scala からの輸入で,リスト内包表記の条件式相当のやつ.基本的には 500 / 100 の範囲で全探索してる.ちゃんとやろうと思えばなんかできそう.<tt class="docutils literal">OverloadedLists</tt> を使ってる弊害で,リストリテラルの表記で,曖昧な型エラーが起きるので,<tt class="docutils literal">Foldable</tt> のインスタンスを type application で固定してる.</p>
</div>
<div class="section" id="some-sums">
<h3>Some Sums<a class="headerlink" href="#some-sums" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
n a b
</pre>
<p class="last"><tt class="docutils literal">n</tt>,<tt class="docutils literal">a</tt>,<tt class="docutils literal">b</tt> は整数</p>
</dd>
<dt>出力</dt>
<dd>1 以上 <tt class="docutils literal">n</tt> 以下で,10 進法での各桁の和が <tt class="docutils literal">a</tt> 以上 <tt class="docutils literal">b</tt> 以下であるものの総和</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">getLineInputs</span><span class="w"> </span><span class="o">@</span><span class="kt">Int</span>
<span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">sum</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="n">n</span><span class="p">],</span><span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sumDigits</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="o"><=</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="p">]</span>
<span class="c1">-- |</span>
<span class="c1">--</span>
<span class="c1">-- >>> sumDigits 11</span>
<span class="c1">-- 2</span>
<span class="c1">--</span>
<span class="nf">sumDigits</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumDigits</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">`</span><span class="n">mod</span><span class="p">`</span><span class="w"> </span><span class="mi">10</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">`</span><span class="n">div</span><span class="p">`</span><span class="w"> </span><span class="mi">10</span>
</pre></div></td></tr></table></div>
<p>リスト内包表記も便利.特に <tt class="docutils literal">length</tt> とか <tt class="docutils literal">sum</tt> とかに食わせる場合は融合変換が効くので,気にしないで書いて良さそう.これはまあ,そのまま安直に問題文の指示通りのことをしてる.</p>
</div>
<div class="section" id="card-game-for-two">
<h3>Card Game for Two<a class="headerlink" href="#card-game-for-two" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
N
a1 ... aN
</pre>
<p class="last"><tt class="docutils literal">N</tt>,<tt class="docutils literal">a1</tt> から <tt class="docutils literal">aN</tt> は整数</p>
</dd>
<dt>出力</dt>
<dd><tt class="docutils literal">a1</tt> から <tt class="docutils literal">aN</tt> を大きい順に2人がそれぞれ出していった時の2人の得点差</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">discardLine</span>
<span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputsMVec</span><span class="w"> </span><span class="o">@</span><span class="kt">Int</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">solve</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="n">r</span>
<span class="c1">-- |</span>
<span class="c1">--</span>
<span class="c1">-- >>> Vec.unsafeThaw [3, 1] >>= solve</span>
<span class="c1">-- 2</span>
<span class="c1">-- >>> Vec.unsafeThaw [20, 18, 2, 18] >>= solve</span>
<span class="c1">-- 18</span>
<span class="c1">--</span>
<span class="nf">solve</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">MVector</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">solve</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">sortBy</span><span class="w"> </span><span class="n">rcompare</span><span class="w"> </span><span class="n">ys</span>
<span class="w"> </span><span class="n">ifoldlMVec'</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">ys</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">.&.</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">negate</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>多分この問題は入力めっちゃ少ないのでそうでもないんだけど,リストのソートめっちゃばんばんメモリ使って GC のお世話になって遅くなるイメージなのでソートは基本的に mutable vector でイントロソートする方針にしてる.そのために mutable vector 向けの API もちょっと書いた.ま,そんな感じです.</p>
</div>
<div class="section" id="kagami-mochi">
<h3>Kagami Mochi<a class="headerlink" href="#kagami-mochi" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
N
d1
...
dN
</pre>
<p class="last"><tt class="docutils literal">N</tt>,<tt class="docutils literal">d1</tt> から <tt class="docutils literal">dN</tt> は整数</p>
</dd>
<dt>出力</dt>
<dd><tt class="docutils literal">d1</tt> から <tt class="docutils literal">dN</tt> を真に小さい順に並べた時の最大の長さ</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">n</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span><span class="w"> </span><span class="o">@</span><span class="kt">Int</span>
<span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">MVector</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">replicateM</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">sort</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="n">xs'</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">Vec</span><span class="o">.</span><span class="n">unsafeFreeze</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="n">print</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">olength</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Vec</span><span class="o">.</span><span class="n">uniq</span><span class="w"> </span><span class="n">xs'</span>
</pre></div></td></tr></table></div>
<p>これもソートしてユニークするだけ.なんか,mutable vector は割と不遇でいろんな API が提供されてない (それは並行並列な世界を考えると当然なんだけど,競プロ的には辛い.もっとゆるふわな API が欲しい).なんで,immutable vector との間を行ったり来たりする必要がある.後,入力部分は毎度おなじみ,曖昧な型を避けるため型指定していけって感じ.</p>
</div>
<div class="section" id="otoshidama">
<h3>Otoshidama<a class="headerlink" href="#otoshidama" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
n y
</pre>
<p class="last"><tt class="docutils literal">n</tt>,<tt class="docutils literal">y</tt> は整数</p>
</dd>
<dt>出力</dt>
<dd><tt class="docutils literal">n</tt> 個 10000 / 5000 / 1000 を使って <tt class="docutils literal">y</tt> を作る組み合わせ.なお,作れない時は <tt class="docutils literal"><span class="pre">-1</span> <span class="pre">-1</span> <span class="pre">-1</span></tt></dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span><span class="w"> </span><span class="o">@</span><span class="kt">Int</span>
<span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">solve</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">Nothing</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"-1 -1 -1"</span>
<span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="p">(</span><span class="n">i1</span><span class="p">,</span><span class="w"> </span><span class="n">i2</span><span class="p">,</span><span class="w"> </span><span class="n">i3</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">prints</span><span class="w"> </span><span class="p">[</span><span class="n">i1</span><span class="p">,</span><span class="w"> </span><span class="n">i2</span><span class="p">,</span><span class="w"> </span><span class="n">i3</span><span class="p">]</span>
<span class="c1">-- |</span>
<span class="c1">--</span>
<span class="c1">-- prop> maybe n (\(x, y, z) -> x + y + z) (solve n $ m * 1000) == n</span>
<span class="c1">-- >>> solve 9 45000</span>
<span class="c1">-- Just ...</span>
<span class="c1">-- >>> solve 20 196</span>
<span class="c1">-- Nothing</span>
<span class="c1">--</span>
<span class="nf">solve</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Maybe</span><span class="w"> </span><span class="p">(</span><span class="kt">Int</span><span class="p">,</span><span class="w"> </span><span class="kt">Int</span><span class="p">,</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span>
<span class="nf">solve</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">headMay</span><span class="w"> </span><span class="o">@</span><span class="p">[</span><span class="kr">_</span><span class="p">]</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="n">n</span><span class="p">]</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">n2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">i1</span>
<span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="n">n2</span><span class="p">]</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">i3</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">n2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">i2</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">y'</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">10000</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">5000</span>
<span class="w"> </span><span class="n">withFilter</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">y'</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">i3</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mi">1000</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="p">(</span><span class="n">i1</span><span class="p">,</span><span class="w"> </span><span class="n">i2</span><span class="p">,</span><span class="w"> </span><span class="n">i3</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>Coins と同じく安直にやってる.所詮,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>200</mn><msup><mn>0</mn><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">2000^2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">200</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></span> やしいけるやろ.今回も曖昧な型回避のため type application してる.type application は特例で partial signature 使えて警告も出ないようになってる.便利.</p>
</div>
<div class="section" id="auto-id-3">
<h3>白昼夢<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
s
</pre>
<p class="last"><tt class="docutils literal">s</tt> は文字列</p>
</dd>
<dt>出力</dt>
<dd><tt class="docutils literal">s</tt> が <tt class="docutils literal">(dream|dreamer|erase|eraser)*</tt> にマッチするか判定し,マッチするなら <tt class="docutils literal">YES</tt>,しないなら <tt class="docutils literal">NO</tt></dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">BS</span><span class="o">.</span><span class="n">getLine</span>
<span class="w"> </span><span class="n">putStrLn</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">solve</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="s">"YES"</span>
<span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="s">"NO"</span>
<span class="c1">-- |</span>
<span class="c1">--</span>
<span class="c1">-- >>> solve "erasedream"</span>
<span class="c1">-- True</span>
<span class="c1">--</span>
<span class="nf">solve</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">ByteString</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">solve</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">parseOnlyEof</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">BS</span><span class="o">.</span><span class="n">reverse</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">Left</span><span class="p">{}</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="kt">Right</span><span class="p">{}</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">True</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Parse</span><span class="o">.</span><span class="n">skipMany</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">altconcat</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="kt">Parse</span><span class="o">.</span><span class="n">try</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Parse</span><span class="o">.</span><span class="n">string</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">BS</span><span class="o">.</span><span class="n">reverse</span><span class="w"> </span><span class="n">w</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">w</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">ws</span><span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="n">ws</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s">"dream"</span><span class="p">,</span><span class="w"> </span><span class="s">"dreamer"</span><span class="p">,</span><span class="w"> </span><span class="s">"erase"</span><span class="p">,</span><span class="w"> </span><span class="s">"eraser"</span><span class="w"> </span><span class="p">]</span>
</pre></div></td></tr></table></div>
<p>接頭が一致してる単語があるので,単純にパーサ書くと早食いしてしまってうまく解けないやつ.でも逆側だと曖昧さがなくなるので逆から書いたがこれは想定解なんだろうか? ところでこの問題,正規表現があれば一発で解決するんだけど,どうやらライブラリリストから抜けてるっぽい.これは投げとくべきだったなと反省してる.今からでも間に合うんやろか? とりあえず質問だけは投げておいた.</p>
</div>
<div class="section" id="traveling">
<h3>Traveling<a class="headerlink" href="#traveling" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入力</dt>
<dd><pre class="first literal-block">
N
t1 x1 y1
...
tN xN yN
</pre>
<p class="last"><tt class="docutils literal">N</tt>,<tt class="docutils literal">t1</tt> から <tt class="docutils literal">tN</tt>,<tt class="docutils literal">x1</tt> から <tt class="docutils literal">xN</tt>,<tt class="docutils literal">y1</tt> から <tt class="docutils literal">yN</tt> は整数</p>
</dd>
<dt>出力</dt>
<dd>時刻 <tt class="docutils literal">t1</tt> から <tt class="docutils literal">tN</tt> でその地点にいれるか判定し,可能なら <tt class="docutils literal">Yes</tt>,できないなら <tt class="docutils literal">No</tt></dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">n</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="n">solve</span><span class="w"> </span><span class="n">n</span>
<span class="nf">solve</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">solve</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"Yes"</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">t'</span><span class="p">,</span><span class="w"> </span><span class="n">x'</span><span class="p">,</span><span class="w"> </span><span class="n">y'</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">abs</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">x'</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">abs</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">y'</span><span class="p">)</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">td</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">t'</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">t</span>
<span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">td</span><span class="w"> </span><span class="o">>=</span><span class="w"> </span><span class="n">d</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="p">(</span><span class="n">td</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">d</span><span class="p">)</span><span class="w"> </span><span class="p">`</span><span class="n">mod</span><span class="p">`</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">t'</span><span class="w"> </span><span class="n">x'</span><span class="w"> </span><span class="n">y'</span>
<span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">replicateM_</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">discardLine</span>
<span class="w"> </span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"No"</span>
</pre></div></td></tr></table></div>
<p>純粋性をかなぐり捨てて書いた.まあ,これはいいでしょ.次行ってみよう.</p>
</div>
<div class="section" id="interactive-sorting">
<h3>Interactive Sorting<a class="headerlink" href="#interactive-sorting" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<dl class="docutils">
<dt>入出力</dt>
<dd><pre class="first literal-block">
n q
</pre>
<p><tt class="docutils literal">(n, q) = (26, 1000), (26, 100), (5, 7)</tt> が最初に提示される</p>
<p><tt class="docutils literal">q</tt> 回大文字アルファベット <tt class="docutils literal">c1</tt>,<tt class="docutils literal">c2</tt> について</p>
<pre class="literal-block">
? c1 c2
</pre>
<p>を出力でき,その度に</p>
<pre class="literal-block">
r
</pre>
<p><tt class="docutils literal">r = <, ></tt> が返ってくる.最後に問合せ結果から分かる <tt class="docutils literal">n</tt> 文字のアルファベットをソートした文字列 <tt class="docutils literal">s</tt> について</p>
<pre class="literal-block">
! s
</pre>
<p class="last">を出力する.</p>
</dd>
</dl>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal"> 10</span>
<span class="normal"> 11</span>
<span class="normal"> 12</span>
<span class="normal"> 13</span>
<span class="normal"> 14</span>
<span class="normal"> 15</span>
<span class="normal"> 16</span>
<span class="normal"> 17</span>
<span class="normal"> 18</span>
<span class="normal"> 19</span>
<span class="normal"> 20</span>
<span class="normal"> 21</span>
<span class="normal"> 22</span>
<span class="normal"> 23</span>
<span class="normal"> 24</span>
<span class="normal"> 25</span>
<span class="normal"> 26</span>
<span class="normal"> 27</span>
<span class="normal"> 28</span>
<span class="normal"> 29</span>
<span class="normal"> 30</span>
<span class="normal"> 31</span>
<span class="normal"> 32</span>
<span class="normal"> 33</span>
<span class="normal"> 34</span>
<span class="normal"> 35</span>
<span class="normal"> 36</span>
<span class="normal"> 37</span>
<span class="normal"> 38</span>
<span class="normal"> 39</span>
<span class="normal"> 40</span>
<span class="normal"> 41</span>
<span class="normal"> 42</span>
<span class="normal"> 43</span>
<span class="normal"> 44</span>
<span class="normal"> 45</span>
<span class="normal"> 46</span>
<span class="normal"> 47</span>
<span class="normal"> 48</span>
<span class="normal"> 49</span>
<span class="normal"> 50</span>
<span class="normal"> 51</span>
<span class="normal"> 52</span>
<span class="normal"> 53</span>
<span class="normal"> 54</span>
<span class="normal"> 55</span>
<span class="normal"> 56</span>
<span class="normal"> 57</span>
<span class="normal"> 58</span>
<span class="normal"> 59</span>
<span class="normal"> 60</span>
<span class="normal"> 61</span>
<span class="normal"> 62</span>
<span class="normal"> 63</span>
<span class="normal"> 64</span>
<span class="normal"> 65</span>
<span class="normal"> 66</span>
<span class="normal"> 67</span>
<span class="normal"> 68</span>
<span class="normal"> 69</span>
<span class="normal"> 70</span>
<span class="normal"> 71</span>
<span class="normal"> 72</span>
<span class="normal"> 73</span>
<span class="normal"> 74</span>
<span class="normal"> 75</span>
<span class="normal"> 76</span>
<span class="normal"> 77</span>
<span class="normal"> 78</span>
<span class="normal"> 79</span>
<span class="normal"> 80</span>
<span class="normal"> 81</span>
<span class="normal"> 82</span>
<span class="normal"> 83</span>
<span class="normal"> 84</span>
<span class="normal"> 85</span>
<span class="normal"> 86</span>
<span class="normal"> 87</span>
<span class="normal"> 88</span>
<span class="normal"> 89</span>
<span class="normal"> 90</span>
<span class="normal"> 91</span>
<span class="normal"> 92</span>
<span class="normal"> 93</span>
<span class="normal"> 94</span>
<span class="normal"> 95</span>
<span class="normal"> 96</span>
<span class="normal"> 97</span>
<span class="normal"> 98</span>
<span class="normal"> 99</span>
<span class="normal">100</span>
<span class="normal">101</span>
<span class="normal">102</span>
<span class="normal">103</span>
<span class="normal">104</span>
<span class="normal">105</span>
<span class="normal">106</span>
<span class="normal">107</span>
<span class="normal">108</span>
<span class="normal">109</span>
<span class="normal">110</span>
<span class="normal">111</span>
<span class="normal">112</span>
<span class="normal">113</span>
<span class="normal">114</span>
<span class="normal">115</span>
<span class="normal">116</span>
<span class="normal">117</span>
<span class="normal">118</span>
<span class="normal">119</span>
<span class="normal">120</span>
<span class="normal">121</span>
<span class="normal">122</span>
<span class="normal">123</span>
<span class="normal">124</span>
<span class="normal">125</span>
<span class="normal">126</span>
<span class="normal">127</span>
<span class="normal">128</span>
<span class="normal">129</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">#</span><span class="n">include</span><span class="w"> </span><span class="s">"../src/Header.hs"</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="p">[</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="kr">_</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readLineInputs</span>
<span class="w"> </span><span class="n">solve</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Vec</span><span class="o">.</span><span class="n">iterateN</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">succ</span><span class="w"> </span><span class="sc">'A'</span>
<span class="nf">solve</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Vector</span><span class="w"> </span><span class="kt">Char</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">solve</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">xs1</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">Vec</span><span class="o">.</span><span class="n">unsafeThaw</span><span class="w"> </span><span class="n">v</span>
<span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="mi">5</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go1</span><span class="w"> </span><span class="n">xs1</span>
<span class="w"> </span><span class="mi">26</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go2</span><span class="w"> </span><span class="n">xs1</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="ne">error</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="s">"unexpected input:"</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">show</span><span class="w"> </span><span class="n">n</span>
<span class="w"> </span><span class="n">xs2</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">Vec</span><span class="o">.</span><span class="n">unsafeFreeze</span><span class="w"> </span><span class="n">xs1</span>
<span class="w"> </span><span class="n">putStr</span><span class="w"> </span><span class="s">"! "</span>
<span class="w"> </span><span class="n">oforM_</span><span class="w"> </span><span class="n">xs2</span><span class="w"> </span><span class="n">putChar</span>
<span class="w"> </span><span class="n">putEndLine</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go1</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">askSwap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">askSwap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="mi">3</span>
<span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="nf">\</span><span class="kr">case</span>
<span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">swap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">2</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">swap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">3</span>
<span class="w"> </span><span class="c1">-- 2 - 3</span>
<span class="w"> </span><span class="c1">-- /</span>
<span class="w"> </span><span class="c1">-- 0 - 1</span>
<span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="nf">\</span><span class="kr">case</span>
<span class="w"> </span><span class="c1">-- 4</span>
<span class="w"> </span><span class="c1">-- /</span>
<span class="w"> </span><span class="c1">-- 2 - 3</span>
<span class="w"> </span><span class="c1">-- /</span>
<span class="w"> </span><span class="c1">-- 0 - 1</span>
<span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">askSwap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="mi">4</span>
<span class="w"> </span><span class="c1">-- 4</span>
<span class="w"> </span><span class="c1">-- \</span>
<span class="w"> </span><span class="c1">-- 2 - 3</span>
<span class="w"> </span><span class="c1">-- /</span>
<span class="w"> </span><span class="c1">-- 0 - 1</span>
<span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">askSwap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">4</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">swap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="mi">2</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">swap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="mi">3</span>
<span class="w"> </span><span class="c1">-- 0 - 2 - 3 - 4</span>
<span class="w"> </span><span class="c1">-- \</span>
<span class="w"> </span><span class="c1">-- 1</span>
<span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="nf">\</span><span class="kr">case</span>
<span class="w"> </span><span class="c1">-- 0 - 2 - 3 - 4</span>
<span class="w"> </span><span class="c1">-- \ /</span>
<span class="w"> </span><span class="c1">-- 1 --</span>
<span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">askSwap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">2</span>
<span class="w"> </span><span class="c1">-- 0 - 2 - 3 - 4</span>
<span class="w"> </span><span class="c1">-- \</span>
<span class="w"> </span><span class="c1">-- 1</span>
<span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">askSwap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">4</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">swap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">swap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">go2</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sortM</span><span class="w"> </span><span class="n">askChar</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="n">askSwap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="nf">\</span><span class="kr">case</span>
<span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">swap</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">i2</span>
<span class="w"> </span><span class="n">ask</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">read</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">i1</span>
<span class="w"> </span><span class="n">c2</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">read</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">i2</span>
<span class="w"> </span><span class="n">askChar</span><span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="n">c2</span>
<span class="w"> </span><span class="n">askChar</span><span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="n">c2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">putStrLn</span><span class="w"> </span><span class="p">[</span><span class="sc">'?'</span><span class="p">,</span><span class="w"> </span><span class="sc">' '</span><span class="p">,</span><span class="w"> </span><span class="n">c1</span><span class="p">,</span><span class="w"> </span><span class="sc">' '</span><span class="p">,</span><span class="w"> </span><span class="n">c2</span><span class="p">]</span>
<span class="w"> </span><span class="n">putFlush</span>
<span class="w"> </span><span class="p">[</span><span class="n">c</span><span class="p">]</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">getLine</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="sc">'<'</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">True</span>
<span class="w"> </span><span class="sc">'>'</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="ne">error</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="s">"unexpected input: "</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="p">[</span><span class="n">c</span><span class="p">]</span>
<span class="c1">-- |</span>
<span class="c1">--</span>
<span class="c1">-- >>> xs <- mvecFromList ['B','A','E','F','D','C']</span>
<span class="c1">-- >>> sortM (\x y -> pure $ x < y) xs</span>
<span class="c1">-- >>> mvecToList xs</span>
<span class="c1">-- "ABCDEF"</span>
<span class="c1">--</span>
<span class="nf">sortM</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Char</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Char</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="kt">Bool</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">MVector</span><span class="w"> </span><span class="kt">Char</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">sortM</span><span class="w"> </span><span class="n">cmp</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">v2</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">clone</span><span class="w"> </span><span class="n">v</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">(</span><span class="kt">MVec</span><span class="o">.</span><span class="n">length</span><span class="w"> </span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="n">v2</span><span class="w"> </span><span class="n">v</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">if</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">i</span>
<span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="p">`</span><span class="n">div</span><span class="p">`</span><span class="w"> </span><span class="mi">2</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">l1</span>
<span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">l1</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="n">merge</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span>
<span class="w"> </span><span class="n">merge</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">if</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">xs2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">slice</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">ys2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">slice</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="n">ys</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">copy</span><span class="w"> </span><span class="n">ys2</span><span class="w"> </span><span class="n">xs2</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">xs1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">slice</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">ys1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">slice</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="n">ys</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">copy</span><span class="w"> </span><span class="n">ys1</span><span class="w"> </span><span class="n">xs1</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">otherwise</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">read</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">i1</span>
<span class="w"> </span><span class="n">c2</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">read</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">i2</span>
<span class="w"> </span><span class="n">cmp</span><span class="w"> </span><span class="n">c1</span><span class="w"> </span><span class="n">c2</span><span class="w"> </span><span class="o">>>=</span><span class="w"> </span><span class="nf">\</span><span class="kr">case</span>
<span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">write</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">c1</span>
<span class="w"> </span><span class="n">merge</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">i1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">l1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">i2</span><span class="w"> </span><span class="n">l2</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span>
<span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kt">MVec</span><span class="o">.</span><span class="n">write</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="n">c2</span>
<span class="w"> </span><span class="n">merge</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">i1</span><span class="w"> </span><span class="n">l1</span><span class="w"> </span><span class="p">(</span><span class="n">i2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">l2</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span>
</pre></div></td></tr></table></div>
<p>率直に言ってめんどくさい.最初に <tt class="docutils literal">n</tt> に関する場合分けをして,<tt class="docutils literal">n = 5</tt> の時は最適なソートを,それ以外の時はマージソートを行う.</p>
<p><tt class="docutils literal">n = 5</tt> の時は,decision tree の葉の数が今回は <tt class="docutils literal">5! = 120</tt> 必要で,2分木の葉の数の限界値は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mi>h</mi></msup></mrow><annotation encoding="application/x-tex">2^h</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">h</span></span></span></span></span></span></span></span></span></span></span></span> なので少なくとも <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi><mo>≥</mo><mn>7</mn></mrow><annotation encoding="application/x-tex">h \geq 7</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">7</span></span></span></span></span> じゃないといけない.ここから最大 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>7</mn></mrow><annotation encoding="application/x-tex">7</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">7</span></span></span></span></span> 回比較がこのソートの最適解だと分かる.逆に言えば decision tree において,選択の幅を狭めるような早めに葉に到達してしまう選択をなるべくしない比較を考えないといけない.で,まあ結果はコードの通り.なるべく対称性を保つような比較を行っていき,徐々に要素の順序を確定させていく.</p>
<p>マージソートの方はそのまんまって感じ.2つの mutable vector 使ってそれぞれの再帰ステップで交互に役割を交代させながらソートしてく.ソートの際 <tt class="docutils literal">IO</tt> が必要で <tt class="docutils literal"><span class="pre">vector-algorithms</span></tt> が使えなかった.これは,テンプレにあったほうがいいんか?</p>
</div>
<div class="section" id="auto-id-4">
<h3>モンスターテイマー<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>問題文を読み解くのがめんどくさかったので,解いてない.</p>
</div>
</div>
<div class="section" id="auto-id-5">
<h2>まとめ<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで AtCoder 用のテンプレ作ったので,良かったら利用してください.僕もやっていきたい (やっていくとは言ってない).DP 関連のサポートがちょっと薄いので,その辺おいおいやりながら整備していきたいねって感じ.</p>
<p>GHC 8.6.5 入ったら,Strict 拡張あるので,全部 unboxed literal と unboxed type 使って書く必要もなさそう.だいぶコーディング体験改善されそうで嬉しいっすね.こちらからは以上です.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/02/haskell-atcoder-template.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/02/haskell-atcoder-template.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>State モナドの代わりに Reader モナドを使う2020-01-30T20:23:21+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2020-01-30:/blog/posts/2020/01/use-reader-instead-of-state/<dl class="docutils">
<dt><strong>注意</strong></dt>
<dd>この記事は公開当時主張に誤りを含んでいたため,大幅に書き直しています.また,公開当時の主張の誤りについ …</dd></dl><dl class="docutils">
<dt><strong>注意</strong></dt>
<dd>この記事は公開当時主張に誤りを含んでいたため,大幅に書き直しています.また,公開当時の主張の誤りについても,付録として載せておきました.</dd>
</dl>
<p>Haskell で State モナドはモナドの代表格だ.Haskell 入門者は,多くの場合,状態を伴った計算を State モナドで書くことを習うだろう.しかし,実用上の多くの場面では,State モナドではなく他の選択肢を選んだ方がいい場合がある.一つの選択肢が,Reader モナドと可変参照を使う方法だ.今回は,この手法を使う利点と利用場面について考えていこうと思う.</p>
<p>なお,環境として以下を想定している.</p>
<table border="1" class="docutils">
<colgroup>
<col width="69%"/>
<col width="31%"/>
</colgroup>
<tbody valign="top">
<tr><td>GHC のバージョン</td>
<td>8.6.5</td>
</tr>
<tr><td>Cabal のバージョン</td>
<td>3.0.0.0</td>
</tr>
</tbody>
</table>
<div class="section" id="ioref">
<h2>IORef の神話<a class="headerlink" href="#ioref" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Haskell はかなり多くの神話を持つ言語だ.その中の一つに,以下のものがある.</p>
<blockquote>
IORef を使うとパフォーマンスは良いが純粋性を損なう.なので,パフォーマンスを気にしないなら State モナドを使うべきだ.</blockquote>
<p>巷の多くの例では,この言葉は都市伝説に過ぎない.まずは,その辺について見ておこう.これは,IORef などの可変参照と State モナドの違いを理解する上でも役に立つはずだし,本記事の良い導入となるだろう.</p>
<p>さて,以下のサンプルコードを見てみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="nn">Control.Monad.State.Strict</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Data.IORef</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">execState</span><span class="w"> </span><span class="p">(</span><span class="n">go</span><span class="w"> </span><span class="n">l</span><span class="p">)</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">modify'</span><span class="w"> </span><span class="nf">\</span><span class="n">s</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">xs</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">newIORef</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">l</span>
<span class="w"> </span><span class="n">readIORef</span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">modifyIORef'</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="nf">\</span><span class="n">s</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">xs</span>
</pre></div></td></tr></table></div>
<p>この場合,<tt class="docutils literal">sumByState</tt> と <tt class="docutils literal">sumByIORef</tt> でどちらがどれくらい良いパフォーマンスを期待できるだろうか? まずは,実測してみよう.<a class="reference external" href="https://hackage.haskell.org/package/criterion">criterion</a> を使って,ベンチマークコードを書いてみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">module</span><span class="w"> </span><span class="nn">Main</span><span class="w"> </span><span class="kr">where</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Criterion.Main</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">Criterion</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Criterion</span><span class="o">.</span><span class="n">defaultMain</span>
<span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="n">bgroup</span><span class="w"> </span><span class="s">"sumByState"</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Criterion</span><span class="o">.</span><span class="n">nf</span><span class="w"> </span><span class="n">sumByState</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">bgroup</span><span class="w"> </span><span class="s">"sumByIORef"</span><span class="w"> </span><span class="nf">\</span><span class="n">xs</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Criterion</span><span class="o">.</span><span class="n">nfIO</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">sumByIORef</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">bgroup</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Criterion</span><span class="o">.</span><span class="n">bgroup</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">benches</span><span class="w"> </span><span class="n">f</span>
<span class="w"> </span><span class="n">benches</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span>
<span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="kt">Criterion</span><span class="o">.</span><span class="n">bench</span><span class="w"> </span><span class="p">(</span><span class="s">"n="</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">show</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">samples</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="n">samples</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="mi">5</span><span class="p">]</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="o">^</span><span class="w"> </span><span class="n">i</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="n">n</span><span class="p">])</span>
</pre></div></td></tr></table></div>
<p>このコードによる測定結果を,グラフにプロットしてみると以下のようになる:</p>
<img alt="``sumByState`` より ``sumByIORef`` の時間の方が常に長い" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2020/01/use-reader-instead-of-state/use-reader-instead-of-state/state-vs-ioref.png"/>
<p>どちらの軸も対数でとってることに注意.見ての通り,常に <tt class="docutils literal">sumByState</tt> の方が <tt class="docutils literal">sumByIORef</tt> より速い.この場合,State モナドは,IORef を使う場合に比べ,「パフォーマンスが良くて,しかも純粋性を損なわない」わけだ.さて,なぜこのような結果になるのだろう? Haskell は純粋性を持つコードを贔屓しているのだろうか? それとも State モナドの実装は,裏で高度な技術が使われていて,それによって高効率な動作をするようになっているのだろうか?</p>
<p>実は,State モナドと IORef のコードは,やってることはそう違いはない.これは,大局的に見てという話ではなく,本当にそれぞれの操作が割と対応したコードになっているのだ.にも関わらず違いが出るのは何故なのだろう? このカラクリを紐解いていこう.GHC では通常最適化レベル 1 でコンパイルをするわけだが,まずは他のレベルでどうなるか見てみよう.<tt class="docutils literal">cabal</tt> を使っている場合は,</p>
<pre class="literal-block">
cabal build --enable-optimization=n && cabal --enable-optimization=n exec ...
</pre>
<p>というようにすれば,試せる.結果は,大体以下のような結果になる:</p>
<dl class="docutils">
<dt>最適化レベル2</dt>
<dd><tt class="docutils literal">sumByIORef</tt> の方はあまり変わらないが,<tt class="docutils literal">sumByState</tt> はさらに性能が良くなり,両者の性能差が浮き彫りになる.</dd>
<dt>最適化レベル0</dt>
<dd><tt class="docutils literal">sumByIORef</tt> の方が <tt class="docutils literal">sumByState</tt> に比べ2倍ほど速くなる.</dd>
</dl>
<p>最適化レベル0の結果から分かる通り,実は State モナドと IORef の性能差は,最適化によって生まれる.最適化レベル1において, <tt class="docutils literal">sumByState</tt> / <tt class="docutils literal">sumByIORef</tt> はそれぞれ概ね次のようなコードに最適化される:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE MagicHash #-}</span>
<span class="cm">{-# LANGUAGE UnboxedTuples #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">GHC.Base</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">GHC.Prim</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="nb">()</span><span class="p">,</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="nb">()</span><span class="p">,</span><span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
<span class="w"> </span><span class="n">y</span><span class="kt">:</span><span class="n">ys</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="p">(</span><span class="n">acc</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">)</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IO</span>
<span class="w"> </span><span class="nf">\</span><span class="n">s0</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">newMutVar</span><span class="o">#</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">s0</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s1</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="o">#</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">coerce</span><span class="w"> </span><span class="p">(</span><span class="kt">STRef</span><span class="w"> </span><span class="n">r</span><span class="o">#</span><span class="p">))</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">s1</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s2</span><span class="p">,</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">readMutVar</span><span class="o">#</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">s2</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IORef</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">State</span><span class="o">#</span><span class="w"> </span><span class="kt">RealWorld</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kt">State</span><span class="o">#</span><span class="w"> </span><span class="kt">RealWorld</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">s0</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s0</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
<span class="w"> </span><span class="n">y</span><span class="kt">:</span><span class="n">ys</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">coerce</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="n">r'</span><span class="o">@</span><span class="p">(</span><span class="kt">STRef</span><span class="w"> </span><span class="n">r</span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">readMutVar</span><span class="o">#</span><span class="w"> </span><span class="n">r</span><span class="o">#</span><span class="w"> </span><span class="n">s0</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s1</span><span class="p">,</span><span class="w"> </span><span class="n">acc</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">writeMutVar</span><span class="o">#</span><span class="w"> </span><span class="n">r</span><span class="o">#</span><span class="w"> </span><span class="p">(</span><span class="n">acc</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">s2</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">coerce</span><span class="w"> </span><span class="n">r'</span><span class="p">)</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="n">s2</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>幾人かは,このコードがまだ最適化の余地を残していることに気づくだろう.実際,最適化レベル2では,さらに w/w という最適化が入り,どちらも余計な処理が省かれる.特に, <tt class="docutils literal">sumByState</tt> はその省かれた処理によって,かなり高速化される.ところでパッと見で, <tt class="docutils literal">sumByState</tt> より <tt class="docutils literal">sumByIORef</tt> の最適化コードは複雑に見える.多くの場合,ミクロな視点で見れば,コードは複雑なものより単純なものの方が速い.実際今回は, <tt class="docutils literal">sumByState</tt> が <tt class="docutils literal">sumByIORef</tt> の方が優っていた.ところが,この2つのコード,実際にやっていることにそう違いはない.IORef は,通常あるヒープ領域を指すポインタとして実装される.そして,そのヒープ領域には,実データのクロージャを指すポインタがやっぱり入っている.そこで,両者の違いは,</p>
<ul class="simple">
<li>実データのクロージャを指すポインタを直接参照するか,一旦実データを指すポインタを参照しさらにそこから実データを参照する2段階の参照か</li>
<li>Haskell の単純な構文を保っているか,<tt class="docutils literal">readMutVar#</tt> / <tt class="docutils literal">writeMutVar#</tt> などのプリミティブな命令が露出しているか</li>
</ul>
<p>になる.ただ,2段階の参照になっても他の処理と比べて相対的にそこまで遅くなるというわけではなく,プリミティブな命令もコード生成時には単純にメモリ参照の命令に置き換わり,特別なランタイム API の呼び出しなどは通常起きない.なので,これらの違いは直接的にはパフォーマンスの違いに影響を及ばさないのだが,間接的には大きな影響を与える.一般に,GHC で IORef が通常の State モナドよりパフォーマンスで劣る点は以下のものだ:</p>
<ul class="simple">
<li>プリミティブな命令をコード生成まで展開できず,そこまでの最適化が阻害される.</li>
<li><tt class="docutils literal">writeMutVar#</tt> は重い処理であり,単純に参照を取り換えるだけでなく,GC への特別な処理を要求する <a class="footnote-reference" href="#notice-write-barrier" id="auto-id-1">[1]</a> .</li>
</ul>
<p>1つ目の問題は,最適化レベル1ではそこまで現れていないが,最適化レベル2で <tt class="docutils literal">sumByIORef</tt> が <tt class="docutils literal">sumByState</tt> に性能差を広げられたことの主な要因になる.w/w 変換で, <tt class="docutils literal">sumByState</tt> は次のように最適化できる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">sumByState</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="mi">0</span><span class="o">#</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="o">#</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="nb">()</span><span class="p">,</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">acc</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="nb">()</span><span class="p">,</span><span class="w"> </span><span class="kt">I</span><span class="o">#</span><span class="w"> </span><span class="n">acc</span><span class="o">#</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
<span class="w"> </span><span class="n">y</span><span class="kt">:</span><span class="n">ys</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">I</span><span class="o">#</span><span class="w"> </span><span class="n">y</span><span class="o">#</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="p">(</span><span class="n">acc</span><span class="o">#</span><span class="w"> </span><span class="o">+#</span><span class="w"> </span><span class="n">y</span><span class="o">#</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>本来の <tt class="docutils literal">+</tt> では, <tt class="docutils literal">I#</tt> を取って <tt class="docutils literal">+#</tt> で計算した結果をまた <tt class="docutils literal">I#</tt> で包むといったことをしてたのが,こうするとその処理が省ける他, <tt class="docutils literal">Int#</tt> の値をいちいちヒープに入れなくて良くなり,かなり速度の改善が見込める.実際,速度はかなり改善する.IORef の方も似たようなことをやってるので,このような最適化を適用しようと思えばできるのだが,残念ながら適用されない.なぜなら,プリミティブ命令は実行コード生成時まで展開されず,最適化の適用にはプリミティブ命令の展開が必要だが,最適化は実行コード生成前に行われるため,結果的にミスマッチにより最適化が適用されないということが起こるからだ.つまり,最適化レベル2での <tt class="docutils literal">sumByState</tt> と <tt class="docutils literal">sumByIORef</tt> の対決は,片方は <tt class="docutils literal">I#</tt> によるラップ処理を省きスタックへの参照のみで完結,もう片方は <tt class="docutils literal">I#</tt> のラップ処理が必要で一々ヒープに書き込む操作も必要といったプログラム同士の悲惨な対決となってしまう.</p>
<p>2つ目の問題は,知るところでは知られた問題だ.一般に writeIORef は幾つかの側面から多用はやめた方がいいと言う通説がある.これは,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">sumByState</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">evalState</span><span class="w"> </span><span class="p">(</span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="mi">10</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">!</span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">y</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">!</span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">get</span>
<span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="p">`</span><span class="n">mod</span><span class="p">`</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="n">put</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">s</span><span class="p">)</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">newIORef</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="p">(</span><span class="mi">10</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">!</span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">y</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">!</span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readIORef</span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="p">`</span><span class="n">mod</span><span class="p">`</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="kr">do</span><span class="w"> </span><span class="n">writeIORef</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">y</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">s</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>のように, <tt class="docutils literal">writeIORef</tt> を抑えたプログラムで速度を実測してみると分かるが,この場合当初は 40% ほどの性能差だったのが 10% ほどになる.つまり,最適化レベル1 での性能悪化の主な要因は,大雑把に言えば <tt class="docutils literal">writeIORef</tt> の多用にあると言うことだ.</p>
<p>これまでの議論 <a class="footnote-reference" href="#notice-optimization-0" id="auto-id-2">[2]</a> から,IORef が State モナドよりパフォーマンスの悪化を招きやすい,少なくとも State モナドより速くなることはないというのが,大方の結論になる.よって,GHC では,IORef より State モナドを使う方が,純粋な計算で完結でき,しかも速いのだ.これが,最初の話題が神話である所以だ.</p>
</div>
<div class="section" id="auto-id-3">
<h2>IORef 再考<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>という話で終わると,単なる注意喚起になってしまうのだが,本題はここからだ.さて,IORef の問題点は以下の2点だった.</p>
<ul class="simple">
<li>プリミティブな命令をコード生成まで展開できず,そこまでの最適化が阻害される.</li>
<li><tt class="docutils literal">writeMutVar#</tt> は重い処理であり,あまり多用してはいけない.</li>
</ul>
<p>これは,別の言い方をすれば,</p>
<ul class="simple">
<li>プリミティブ命令を展開するような最適化が,そこまでパフォーマンスに大きく影響しない</li>
<li><tt class="docutils literal">writeMutVar#</tt> をそこまで多用しない</li>
</ul>
<p>コードであれば,IORef は有効ということになるのではないだろうか? 1つ目の用件は,スタック領域だけで完結しないような状態,つまり <tt class="docutils literal">Int</tt> のようなものでなく <tt class="docutils literal">Bool</tt> のような本質的に boxed なデータを扱うコードであれば,大体クリアできる. <tt class="docutils literal">writeMutVar#</tt> についても,頻繁に変更しないが,参照は頻繁に行うような要件はいくらでもあるだろう.特に,今回対象にしたいのが,グローバルコンテキストだ.グローバルコンテキストの賛否はともかくとして,現実の多くのプログラムは,巨大で常駐し続けるプログラムの設定を管理するデータを持っている.通常グローバルコンテキストは,幾つかのフィールドから構成されていて,ネストされていたりもする.フィールドの中身はヒープに確保しなければいけないため,1つ目の条件を満たす.さらに,その中の幾つかのフィールドは変更可能なものになっている場合があり,起動してからいくつかのタイミングで更新される可能性がある.しかし,それほど頻繁な変更ではないため,2つ目の条件も満たすことになる.つまり,グローバルコンテキストは先ほど挙げた2点を満たしているのだ.このような状況設定だと,IORef と State モナドのパフォーマンスは同等になる場合が多い.例えば,次の例を見てみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span>
<span class="normal">62</span>
<span class="normal">63</span>
<span class="normal">64</span>
<span class="normal">65</span>
<span class="normal">66</span>
<span class="normal">67</span>
<span class="normal">68</span>
<span class="normal">69</span>
<span class="normal">70</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE StrictData #-}</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Context</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Context</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">SubContext</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">String</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param3</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Ordering</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param4</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="w"> </span><span class="p">}</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">SubContext</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">SubContext</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">subparam2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">subparam3</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">String</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">subparam4</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Ordering</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">initialContext</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Context</span><span class="w"> </span><span class="n">a</span>
<span class="nf">initialContext</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Context</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">SubContext</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">subparam2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">subparam3</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s">"str1"</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">subparam4</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">EQ</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">True</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s">"str2"</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param3</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">EQ</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param4</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Context</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">execState</span><span class="w"> </span><span class="p">(</span><span class="n">go</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">initialContext</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Integer</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">State</span><span class="w"> </span><span class="p">(</span><span class="kt">Context</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="mi">10000</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">goUpdate</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">goUpdate</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">get</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="p">(</span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="n">put</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">s</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="p">(</span><span class="kt">Context</span><span class="w"> </span><span class="p">(</span><span class="kt">IORef</span><span class="w"> </span><span class="kt">Int</span><span class="p">))</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">newIORef</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">initialContext</span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Context</span><span class="w"> </span><span class="p">(</span><span class="kt">IORef</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Integer</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="mi">10000</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">goUpdate</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">goUpdate</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">readIORef</span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="n">writeIORef</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>この例は色々細工がしてあるが,とにかくこの場合,入力リストの長さを 100000 より大きくすると,最適化レベル1 / 2 両方で, <tt class="docutils literal">sumByIORef</tt> と <tt class="docutils literal">sumByState</tt> は大体同等の性能か,IORef の方がほんの少し速くなる.細工の内容としては,</p>
<ul class="simple">
<li>コンテキストの更新の合間に,余計な Integer オブジェクトを作り出し GC させることで,コンテキストの内容自体の世代を成長させてから GC に回収させる.</li>
<li>フィールドを多くすることで,State モナドの場合に更新に手間がかかるようにしている.</li>
</ul>
<p>という感じ.この例は結構無理やり作っているけど,実際コンテキストはそこそこフィールドが多くネストしていて,書き込みが少ないことから内容も世代を超えやすいはずなので,現実の条件を擬似的に作り出してる例と言えると思う.よって,グローバルコンテキストに対し IORef を適用するならば,パフォーマンス的な心配はしなくて良いと言えるのではないだろうか? さらに,IORef が State モナドより勝る点として以下のものがある.</p>
<ul class="simple">
<li>可変なフィールドを明示することができ,データ定義から可変な箇所がわかるようになる.</li>
<li>値の変更の際,State モナドでは読み込み,書き込み両方でデータのネスト構造を辿る必要があったのが,IORef では読み込みのみでよくなる.</li>
</ul>
<p>今回の例は, <tt class="docutils literal">Context Int</tt> をちゃんと書き下せば, <tt class="docutils literal">subparam1</tt> フィールドを unpack できる.この場合, IORef は boxed なものしか扱えないため,ちょっと不利かもしれないが,そこら辺も <a class="reference external" href="https://hackage.haskell.org/package/unboxed-ref">unboxed-ref</a> 使えばいい勝負ができるんじゃないかなと思ってる (が,試してない.また時間があれば,試してみたい).</p>
<p>ただ注意として, <tt class="docutils literal">writeIORef</tt> は局所的に頻繁に呼び出すような場面には向いてないので,その場合は一旦 IORef から取り出して再帰関数の累積引数として引き回したり,そういう時こそ State モナドで最終的な値を作ってから,IORef に入れ直すのが無難.更新の間に色々処理が挟まるようだったら, <tt class="docutils literal">writeIORef</tt> や <tt class="docutils literal">modifyIORef</tt> 使ってもいいかもねって感じ.</p>
</div>
<div class="section" id="reader-ioref">
<h2>Reader + IORef<a class="headerlink" href="#reader-ioref" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,先ほど挙げた <tt class="docutils literal">sumByIORef</tt> は Reader モナドを使うと次のように書き換えられる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="nn">Control.Monad.Reader</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Control.Monad.IO.Class</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">App</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">ReaderT</span><span class="w"> </span><span class="p">(</span><span class="kt">Context</span><span class="w"> </span><span class="p">(</span><span class="kt">IORef</span><span class="w"> </span><span class="kt">Int</span><span class="p">))</span><span class="w"> </span><span class="kt">IO</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">App</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Integer</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">App</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="mi">10000</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">goUpdate</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">goUpdate</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">ask</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">liftIO</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">readIORef</span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="n">liftIO</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">writeIORef</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">$!</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>本来, <tt class="docutils literal">State</tt> が補っていた部分を,読み込み部分は <tt class="docutils literal">ReaderT</tt> に,可変部分は <tt class="docutils literal">IORef</tt> と <tt class="docutils literal">IO</tt> に任せる感じだ.このようなプログラミングスタイルは,何も僕が思いついたわけではなく, <a class="reference external" href="https://www.fpcomplete.com/blog/2017/06/readert-design-pattern">ReaderT パターン</a> と呼ばれていて,結構最近は浸透しつつあるんかな? 今まで挙げたコードの清潔さを担保するという他にも,このスタイルはメリットがあり,もうちょっと周辺のツールも整備されてたりするんだけど,まあ詳細は <a class="reference external" href="https://www.fpcomplete.com/blog/2017/06/readert-design-pattern">元記事</a> の方を読んでくれ.(飽きてきた.)</p>
</div>
<div class="section" id="auto-id-5">
<h2>まとめ<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,状態更新を行う時の代表手法として紹介される State モナドだけど,Reader + IORef を使った方が見通しがいい場合もあるよという話でした.パフォーマンス面での話は,誰も挙げていない気がしたので書いた感じ.</p>
<p>大雑把には,State モナドより Reader + IORef を使った方がいい場合として,状態が</p>
<ul class="simple">
<li>大きくてネストしていたりというように,ほどほどに複雑で</li>
<li>頻繁には変更しなくて</li>
<li>局所的な変更が多くて (変更しない部分も多くて)</li>
</ul>
<p>という条件を満たす時というのがある.この場合は,State よりも Reader + IORef の方がコードの簡潔さ的に良い場合があり,パフォーマンス面でもそこまで有意差はないよという感じ.今回は,IORef しか紹介しなかったけど,これは TVar とかにも通じる話だし,STRef 使えば全体として純粋に計算できる場合もある.ま,そういう感じで (ざつぅ).</p>
</div>
<div class="section" id="auto-id-6">
<h2>誤りのあった主張<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>そもそもの目算として,ネストするような状態で奥深くを更新する場合は,IORef の方がパフォーマンス的にも優位なのではないかというのがあったんだけど,これはあまり大きな差ではなさそうだった.まず,当初この記事で挙げていた以下の例で,ネストする状態の分解と構成が重いため, <tt class="docutils literal">sumByState</tt> より <tt class="docutils literal">sumByIORef</tt> の方が速いという主張は誤りだった ( <a class="reference external" href="https://github.com/maoe">maoe</a> さんの <a class="reference external" href="https://github.com/mizunashi-mana/blog/pull/85#discussion_r373787772">指摘</a> で判明した. <a class="reference external" href="https://github.com/maoe">maoe</a> さん,ありがとうございます).</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Context</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Context</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">SubContext</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">String</span>
<span class="w"> </span><span class="p">}</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">SubContext</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">SubContext</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">subparam2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">initialContext</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Context</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">SubContext</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">subparam2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">True</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">param2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="s">""</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Context</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sumByState</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">execState</span><span class="w"> </span><span class="p">(</span><span class="n">go</span><span class="w"> </span><span class="n">l</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">initialContext</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">modify'</span><span class="w"> </span><span class="nf">\</span><span class="n">ctx</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="p">(</span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">xs</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="p">(</span><span class="kt">Context</span><span class="w"> </span><span class="p">(</span><span class="kt">IORef</span><span class="w"> </span><span class="kt">Int</span><span class="p">))</span>
<span class="nf">sumByIORef</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">newIORef</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">initialContext</span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="n">l</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="n">modifyIORef'</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="nf">\</span><span class="n">s</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">ctx</span><span class="w"> </span><span class="n">xs</span>
</pre></div></td></tr></table></div>
<p>この例で問題だったのは, <tt class="docutils literal">sumByState</tt> の</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">modify'</span><span class="w"> </span><span class="nf">\</span><span class="n">ctx</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="p">(</span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>の部分で,大幅に効率が悪かったのはこの部分でスペースリークが発生していたからだった.この場合 <tt class="docutils literal">modify'</tt> が更新値を WHNF に評価しても,ネストした部分の <tt class="docutils literal">subctx</tt> に入る値は評価されずサンクになる.このサンクは,最終的に返ってくる <tt class="docutils literal">Context Int</tt> の値を NF に評価するまで積み上がり,その評価の時点で初めて潰されることになる.このスペースリークが, <tt class="docutils literal">sumByState</tt> が遅くなっていた要因で,解決策は <tt class="docutils literal">Context a</tt> / <tt class="docutils literal">SubContext a</tt> を <tt class="docutils literal">StrictData</tt> にするか,以下のように <tt class="docutils literal">subparam1</tt> に入れる値を NF にすれば良い:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">modify'</span><span class="w"> </span><span class="nf">\</span><span class="n">ctx</span><span class="w"> </span><span class="ow">-></span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="o">!</span><span class="n">s</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="p">(</span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="n">ctx</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subctx</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">subctx</span><span class="w"> </span><span class="n">ctx</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">subparam1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">s</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>こうすると, <tt class="docutils literal">sumByState</tt> は <tt class="docutils literal">sumByIORef</tt> より速くなり,パフォーマンスが改善するというのは誤りだったということになる.では,実際状態の分解と構成はまるっきり無視できるかというと,一応は影響するらしい.今回差し替えた,色々細工を加えた例では,最適化レベル1では 10% ほど <tt class="docutils literal">sumByState</tt> が <tt class="docutils literal">sumByIORef</tt> より性能が悪化するという結果になった.ところが,最適化レベル2になると,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">A</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">n2</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">n2</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">A</span><span class="w"> </span><span class="n">n1</span><span class="w"> </span><span class="n">n2</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="n">n2</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">n1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span>
</pre></div></td></tr></table></div>
<p>を,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f</span><span class="w"> </span><span class="p">(</span><span class="kt">A</span><span class="w"> </span><span class="p">(</span><span class="kt">I</span><span class="o">#</span><span class="w"> </span><span class="n">n1</span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">I</span><span class="o">#</span><span class="w"> </span><span class="n">n2</span><span class="o">#</span><span class="p">))</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">n1</span><span class="o">#</span><span class="w"> </span><span class="n">n2</span><span class="o">#</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="mi">0</span><span class="o">#</span><span class="w"> </span><span class="n">m2</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">I</span><span class="o">#</span><span class="w"> </span><span class="n">m2</span><span class="o">#</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m1</span><span class="o">#</span><span class="w"> </span><span class="n">m2</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">m2</span><span class="o">#</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">m1</span><span class="o">#</span><span class="w"> </span><span class="o">-#</span><span class="w"> </span><span class="mi">1</span><span class="o">#</span>
</pre></div></td></tr></table></div>
<p>にするような最適化 <a class="footnote-reference" href="#notice-datatype-ww" id="auto-id-8">[3]</a> が入り,ネストも平坦になるため一切分解と構成のオーバーヘッドはかからない.また,内部の値も unbox 化されるので,結構コスト削減になってるはずなのだが,代わりにかなり多くの引数を再帰関数で引き回す必要があるため,そこらへんがオーバーヘッドになって,結局 IORef と同程度にしかパフォーマンスが出せてないみたい (ちょっと詳細はまだ調査できていない).</p>
<p>とりあえず,当初の IORef の場合 State モナドに比べてパフォーマンスが改善する場合もあるというのは,事実となる場合もあるはあるがそこまで大きな有意差ではなく,書くコードと入る最適化によって十分覆る程度のものみたい.なので,パフォーマンスが改善するというよりは,パフォーマンスにそこまで有意差はないと言った方が実態に即している気がしたので,全体的に取り下げることにした.</p>
<table class="docutils footnote" frame="void" id="notice-write-barrier" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td>GHC では,GC の捕捉のため旧世代から新世代への参照が作られた場合の更新通知を,mutator が行う必要がある.この通知を <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/wikis/commentary/rts/storage/gc/remembered-sets">write barrier</a> と呼んでいて,writeMutVar# も write barrier を内部で行う.しかし,write barrier があまりにも多いと,内部の仕組み的に GC の性能が下がるという問題が知られている.一般に,GHC の GC は可変なオブジェクトについてあまり良いサポートを提供できていないと言う <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/issues/7662">話</a> もある.その意味では,純粋性を贔屓しているというのは正しい.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-optimization-0" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td>最適化レベル0,つまり最適化なしの場合,IORef の方が速くなる現象にはここまで触れなかったが,実はこれは State のせいというより mtl のせいという側面が大きい.普段私たちはそこまで意識していないのだが,実は型クラスを使うのにはそれなりの実行時コストがかかる.これらは,最適化によってそれなりに排除されている.しかし,最適化なしの場合はこのコストはもろに影響してくる.今回の場合は, <tt class="docutils literal">IO</tt> モナドだけを使ったコードと比較し, <tt class="docutils literal">State</tt> モナドのコードは mtl の API を使ったので <tt class="docutils literal">Monad</tt> 型クラスと <tt class="docutils literal">MonadState</tt> 型クラスの抽象化に依存している.つまり,その分コストが増えてしまったということになる.なので,最適化なしの場合は,あまり本質的な違いとは言えないだろう.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-datatype-ww" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-8">[3]</a></td><td>データ型に対する w/w の一種みたい: <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/data-types#the-constructor-wrapper-functions">https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/data-types#the-constructor-wrapper-functions</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2020/01/use-reader-instead-of-state.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2020/01/use-reader-instead-of-state.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>始代数と終余代数が一致する条件2019-12-16T11:16:48+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-12-16:/blog/posts/2019/12/algebraic-compact-functor/<p><a class="reference external" href="http://ziphil.com/diary/application/26.html">http://ziphil.com/diary/application/26.html</a> を読んでるとき,まとめたことを記事として残しておこうと思った.</p>
<p>参考文献は,</p>
<blockquote>
Barr, M. (1992). Algebraically compact functors. Journal of Pure …</blockquote><p><a class="reference external" href="http://ziphil.com/diary/application/26.html">http://ziphil.com/diary/application/26.html</a> を読んでるとき,まとめたことを記事として残しておこうと思った.</p>
<p>参考文献は,</p>
<blockquote>
Barr, M. (1992). Algebraically compact functors. Journal of Pure and Applied Algebra, 82(3), 211–231. <a class="reference external" href="https://doi.org/10.1016/0022-4049(92)90169-G">https://doi.org/10.1016/0022-4049(92)90169-G</a></blockquote>
<p>なお以降考える圏は,特に断りのない限り, initial object 0 及び terminal object 1 が存在し,chain cocomplete (chain に対する図式が colimit を持つ) で cochain complete (cochain に対する図式が limit を持つ) であるとする.</p>
<div class="section" id="f-algebra-f-coalgebra">
<h2>F-algebra と F-coalgebra<a class="headerlink" href="#f-algebra-f-coalgebra" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span>,自己関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> において,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra は,射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>X</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>a</mi></mpadded></mover><mi>X</mi></mrow><annotation encoding="application/x-tex">F X \xrightarrow{a} X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">FX</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> のこと.で,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra 同士の射を以下の図式を可換にする射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi></mrow><annotation encoding="application/x-tex">h</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span></span></span></span></span> (<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra 準同型射と呼ぶ)</p>
<img alt=":math:`F X_1 \xrightarrow{a_1} X_1`,:math:`F X_2 \xrightarrow{a_2} X_2` に対して,:math:`f \circ a_1 = a_2 \circ F f` を満たす :math:`X_1 \xrightarrow{h} X_2`" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/12/algebraic-compact-functor/algebraic-compact-functor/f-algebra-homomorphism.png"/>
<p>とすると, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra による圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi mathvariant="normal">A</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">g</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>F</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{Alg}_C(F)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm" style="margin-right:0.01389em;">Alg</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2342em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mclose">)</span></span></span></span></span> を構成できる.この圏で initial object が存在したとき,それを initial <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra と呼ぶ.その双対をそれぞれ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-coalgebra , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">A</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">g</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>F</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{CoAlg}_C(F)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm" style="margin-right:0.01389em;">CoAlg</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2342em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mclose">)</span></span></span></span></span> ,terminal <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-coalgebra と呼ぶ.</p>
<p>ところで, initial algebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>a</mi></mpadded></mover><mi>A</mi></mrow><annotation encoding="application/x-tex">F A \xrightarrow{a} A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> において, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>A</mi><mo>∼</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">F A \sim A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> であることが知られている.</p>
<dl class="docutils">
<dt>定理. (Lambek's Theorem)</dt>
<dd><p class="first">自己関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> において,initial <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>a</mi></mpadded></mover><mi>A</mi></mrow><annotation encoding="application/x-tex">F A \xrightarrow{a} A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> があるとする.この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> は同型射.</p>
<p>証明:</p>
<p>以下の図式は可換:</p>
<img alt="initial algebra に :math:`F` を適用したものを介した, initial algebra から initial algebra への合成射" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/12/algebraic-compact-functor/algebraic-compact-functor/initial-f-algebra-iso.png"/>
<p class="last">よって, initial algebra からの射の一意性から,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><mi>a</mi><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">a^{-1}; a = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span>.さらに,左の図式だけ考えると <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">;</mo><msup><mi>a</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo>=</mo><mi>F</mi><msup><mi>a</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><mi>F</mi><mi>a</mi><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>a</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><mi>a</mi><mo stretchy="false">)</mo><mo>=</mo><mi>F</mi><mtext> </mtext><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">a; a^{-1} = F a^{-1}; F a = F (a^{-1}; a) = F\, \mathrm{id} = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> は同型射になる.</p>
</dd>
</dl>
<p>双対的に, terminal <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-coalgebra についても同型であることが示せる.ところで, initial / terminal object から initial algebra / terminal coalgebra を構成できる場合がある.それは,initial / terminal sequence が途中で同型の列になる場合である.</p>
<dl class="docutils">
<dt>定義. (initial / terminal <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-sequence)</dt>
<dd><p class="first">以下の順序数で添字づけられた図式を (ordinal) initial <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-sequence と呼ぶ.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi mathvariant="normal">∃</mi><mo stretchy="false">!</mo><mi>f</mi></mrow></mpadded></mover><mi>F</mi><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi>F</mi><mi>f</mi></mrow></mpadded></mover><msup><mi>F</mi><mn>2</mn></msup><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><msup><mi>F</mi><mn>2</mn></msup><mi>f</mi></mrow></mpadded></mover><mo>⋯</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><msup><mi>F</mi><mi>ω</mi></msup><mi>f</mi></mrow></mpadded></mover><mo>⋯</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><msup><mi>F</mi><mi>α</mi></msup><mi>f</mi></mrow></mpadded></mover><mo>⋯</mo></mrow><annotation encoding="application/x-tex">
0 \xrightarrow{\exists ! f} F 0 \xrightarrow{F f} F^2 0 \xrightarrow{F^2 f} \cdots F^\omega 0 \xrightarrow{F^\omega f} \cdots F^\alpha 0 \xrightarrow{F^\alpha f} \cdots
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">∃</span><span class="mclose mtight">!</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.15em;vertical-align:-0.011em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.139em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.15em;vertical-align:-0.011em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.139em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.313em;"></span><span class="minner">⋯</span></span></span></span></span></div>
<p>なお,任意の順序数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo separator="true">,</mo><mi>β</mi><mo>≤</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha, \beta \leq \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn></mrow><annotation encoding="application/x-tex">F^\alpha 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn></mrow><annotation encoding="application/x-tex">f^\beta_\alpha: F^\beta 0 \to F^\alpha 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span></span></span></span></span> を,以下のように定める:</p>
<dl class="docutils">
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\alpha = 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span> の時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mn>0</mn></msup><mn>0</mn><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">F^0 0 = 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mn>0</mn><mn>0</mn></msubsup><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">f^0_0 = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0622em;vertical-align:-0.2481em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span></dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\alpha = 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> の時</dt>
<dd><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mn>1</mn></msup><mn>0</mn><mo>=</mo><mi>F</mi><mn>0</mn></mrow><annotation encoding="application/x-tex">F^1 0 = F 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span></span></span></span></span>,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mn>1</mn><mi>β</mi></msubsup><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>f</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>β</mi><mo>=</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>β</mi><mo>=</mo><mi>α</mi><mo>=</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
f^\beta_1 = \left\{\begin{array}{ll}
f &(\beta = 0) \\
\mathrm{id} &(\beta = \alpha = 1)
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2333em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.4337em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">id</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> が極限順序数の時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><msub><mo stretchy="false">)</mo><mrow><mi>β</mi><mo><</mo><mi>α</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(f^\beta_\alpha: F^\beta 0 \to F^\alpha 0)_{\beta < \alpha}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> は chain <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><msub><mo stretchy="false">)</mo><mrow><mi>β</mi><mo><</mo><mi>α</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(F^\beta 0)_{\beta < \alpha}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1352em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> の colimit で定める.また,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>α</mi></msubsup><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">f^\alpha_\alpha = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span></dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mi>γ</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\alpha = \gamma + 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> で,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>γ</mi></mrow><annotation encoding="application/x-tex">\gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span></span></span></span></span> が極限順序数の時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>γ</mi></msup><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F^\alpha 0 = F (F^\gamma 0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span> とする.この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo><</mo><mi>γ</mi></mrow><annotation encoding="application/x-tex">\beta < \gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span></span></span></span></span> に対して,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup><mo>=</mo><msubsup><mi>f</mi><mrow><mi>β</mi><mo>+</mo><mn>1</mn></mrow><mi>β</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>f</mi><mi>γ</mi><mi>β</mi></msubsup></mrow><annotation encoding="application/x-tex">f^\beta_\alpha = f^\beta_{\beta + 1}; F f^\beta_\gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.4044em;vertical-align:-0.4374em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.3987em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4374em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3831em;"><span></span></span></span></span></span></span></span></span></span></span> とおくと,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><msub><mo stretchy="false">)</mo><mrow><mi>β</mi><mo><</mo><mi>γ</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(f^\beta_\alpha: F^\beta 0 \to F^\alpha)_{\beta < \gamma}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> は cocone になるので一意射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>γ</mi></msubsup></mrow><annotation encoding="application/x-tex">f^\gamma_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> が存在する.これらで <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo>≤</mo><mi>γ</mi></mrow><annotation encoding="application/x-tex">\beta \leq \gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span></span></span></span></span> については <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup></mrow><annotation encoding="application/x-tex">f^\beta_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> を定める.また,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>α</mi></msubsup><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">f^\alpha_\alpha = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span></dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mi>γ</mi><mo>+</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">\alpha = \gamma + 2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span></span></span></span></span> と書ける時 (つまり,上記以外の場合)</dt>
<dd><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>α</mi></msup><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mrow><mi>γ</mi><mo>+</mo><mn>1</mn></mrow></msup><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F^\alpha = F (F^{\gamma + 1} 0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span>,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msubsup><mi>f</mi><mrow><mi>γ</mi><mo>+</mo><mn>1</mn></mrow><mi>β</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>f</mi><mrow><mi>γ</mi><mo>+</mo><mn>1</mn></mrow><mi>γ</mi></msubsup></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>β</mi><mo>≤</mo><mi>γ</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>β</mi><mo>=</mo><mi>α</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
f^\beta_\alpha = \left\{\begin{array}{ll}
f^\beta_{\gamma + 1}; F f^\gamma_{\gamma + 1} &(\beta \leq \gamma + 1) \\
\mathrm{id} &(\beta = \alpha)
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1461em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.5694em;vertical-align:-1.0347em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.5347em;"><span style="top:-3.5677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.4337em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4024em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7823em;"><span style="top:-2.4337em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4024em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.3253em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">id</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.0347em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.5347em;"><span style="top:-3.5677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span><span style="top:-2.3253em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.0347em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
</dd>
</dl>
<p>この定義が well-defined であること,以下が成り立つことは帰納法により容易に示せる:</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mrow><mi>α</mi><mo>+</mo><mn>1</mn></mrow></msup><mn>0</mn><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F^{\alpha + 1} 0 = F (F^\alpha 0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mrow><mi>α</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>β</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo>=</mo><mi>F</mi><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup></mrow><annotation encoding="application/x-tex">f^{\beta + 1}_{\alpha + 1} = F f^\beta_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2917em;vertical-align:-0.3246em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.4337em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>α</mi></msubsup><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">f^\alpha_\alpha = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo>≤</mo><mi>γ</mi><mo>≤</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\beta \leq \gamma \leq \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> の時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>γ</mi><mi>β</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>α</mi><mi>γ</mi></msubsup><mo>=</mo><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup></mrow><annotation encoding="application/x-tex">f^\beta_\gamma; f^\gamma_\alpha = f^\beta_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2322em;vertical-align:-0.3831em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3831em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p>また,以下の順序数で添字づけられた反変図式を (ordinal) terminal <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-sequence と呼ぶ.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">←</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi mathvariant="normal">∃</mi><mo stretchy="false">!</mo><mi>g</mi></mrow></mpadded></mover><mi>F</mi><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">←</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi>F</mi><mi>g</mi></mrow></mpadded></mover><msup><mi>F</mi><mn>2</mn></msup><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">←</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><msup><mi>F</mi><mn>2</mn></msup><mi>g</mi></mrow></mpadded></mover><mo>⋯</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">←</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><msup><mi>F</mi><mi>ω</mi></msup><mi>g</mi></mrow></mpadded></mover><mo>⋯</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><msup><mi>F</mi><mi>α</mi></msup><mi>g</mi></mrow></mpadded></mover><mo>⋯</mo></mrow><annotation encoding="application/x-tex">
1 \xleftarrow{\exists ! g} F 1 \xleftarrow{F g} F^2 1 \xleftarrow{F^2 g} \cdots F^\omega 1 \xleftarrow{F^\omega g} \cdots F^\alpha 1 \xrightarrow{F^\alpha g} \cdots
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">∃</span><span class="mclose mtight">!</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMinYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M400000 241H110l3-3c68.7-52.7 113.7-120
135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8
-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247
c-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208
490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3
1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202
l-3-3h399890zM100 241v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1113em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1003em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMinYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M400000 241H110l3-3c68.7-52.7 113.7-120
135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8
-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247
c-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208
490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3
1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202
l-3-3h399890zM100 241v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMinYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M400000 241H110l3-3c68.7-52.7 113.7-120
135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8
-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247
c-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208
490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3
1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202
l-3-3h399890zM100 241v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.15em;vertical-align:-0.011em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.139em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMinYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M400000 241H110l3-3c68.7-52.7 113.7-120
135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8
-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247
c-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208
490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3
1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202
l-3-3h399890zM100 241v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.15em;vertical-align:-0.011em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.139em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.313em;"></span><span class="minner">⋯</span></span></span></span></span></div>
<p class="last">この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span>,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>g</mi><mi>α</mi><mi>β</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>1</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">g^\beta_\alpha: F^\beta 1 \to F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> を initial sequence と双対的に定める.</p>
</dd>
</dl>
<p>initial / terminal sequence が途中で同型の列になる時,その列は停止するという.</p>
<dl class="docutils">
<dt>定義. (initial / terminal sequence の停止性)</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mrow><mi>α</mi><mo>+</mo><mn>1</mn></mrow><mi>α</mi></msubsup></mrow><annotation encoding="application/x-tex">f^\alpha_{\alpha + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0009em;vertical-align:-0.3064em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span></span></span></span></span> が同型になる時,initial sequence は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> で停止するという.双対的に,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>g</mi><mi>α</mi><mrow><mi>α</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow><annotation encoding="application/x-tex">g^{\alpha + 1}_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0611em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> が同型になる時,terminal sequence は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> で停止するという.</dd>
</dl>
<p>なお,関手は同型を保存するので <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> で停止する initial sequence は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> 以降の射が全て同型射になる.ところで,initial sequence の停止性の条件に,次のものがある.</p>
<dl class="docutils">
<dt>命題.</dt>
<dd><p class="first">ある <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo separator="true">,</mo><mi>β</mi><mo><</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha, \beta < \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> で,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup></mrow><annotation encoding="application/x-tex">f^\beta_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> が同型射ならば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mrow><mi>β</mi><mo>+</mo><mn>1</mn></mrow><mi>β</mi></msubsup></mrow><annotation encoding="application/x-tex">f^\beta_{\beta + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.4044em;vertical-align:-0.4374em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.3987em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4374em;"><span></span></span></span></span></span></span></span></span></span></span> は同型射</p>
<p>証明:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup><mo>=</mo><msubsup><mi>f</mi><mrow><mi>α</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>β</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo>=</mo><msubsup><mi>f</mi><mi>α</mi><mrow><mi>β</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mrow><mi>α</mi><mo>+</mo><mn>1</mn></mrow><mi>α</mi></msubsup></mrow><annotation encoding="application/x-tex">
F f^\beta_\alpha = f^{\beta + 1}_{\alpha + 1} = f^{\beta + 1}_\alpha; f^\alpha_{\alpha + 1}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1461em;vertical-align:-0.247em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2917em;vertical-align:-0.3246em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.4337em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2044em;vertical-align:-0.3053em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3053em;"><span></span></span></span></span></span></span></span></span></span></span></div>
<p>より,以下の図式が可換:</p>
<img alt=":math:`F f^\beta_\alpha = f^{\beta + 1}_\alpha; f^\alpha_{\alpha + 1}`,:math:`f^\beta_\alpha = f^\beta_{\beta + 1}; f^{\beta + 1}_\alpha` への同型射の分解" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/12/algebraic-compact-functor/algebraic-compact-functor/initial-sequence-terminates.png"/>
<p class="last">この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mrow><mi>β</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow><annotation encoding="application/x-tex">f^{\beta + 1}_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> は同型射になり,よって <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mrow><mi>β</mi><mo>+</mo><mn>1</mn></mrow><mi>β</mi></msubsup></mrow><annotation encoding="application/x-tex">f^\beta_{\beta + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.4044em;vertical-align:-0.4374em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.3987em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4374em;"><span></span></span></span></span></span></span></span></span></span></span> も同型射になる.</p>
</dd>
</dl>
<p>なお,上記の命題で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>α</mi><mrow><mi>β</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow><annotation encoding="application/x-tex">f^{\beta + 1}_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> が同型射になることは,以下の命題から分かる.</p>
<dl class="docutils">
<dt>命題.</dt>
<dd><p class="first">ある射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>:</mo><mi>A</mi><mo>→</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">a: A \to B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">;</mo><msub><mi>b</mi><mn>1</mn></msub><mo>:</mo><mi>A</mi><mo>→</mo><mi>A</mi><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">a; b_1: A \to A = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>b</mi><mn>1</mn></msub><mo>:</mo><mi>B</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">b_1: B \to A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> と,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>b</mi><mn>2</mn></msub><mo separator="true">;</mo><mi>a</mi><mo>:</mo><mi>B</mi><mo>→</mo><mi>B</mi><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">b_2; a: B \to B = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>b</mi><mn>2</mn></msub><mo>:</mo><mi>B</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">b_2: B \to A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> を持つ時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> は同型射 <a class="footnote-reference" href="#notice-split-mono-and-split-epi" id="auto-id-2">[2]</a></p>
<p>証明:</p>
<p class="last"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>b</mi><mn>1</mn></msub><mo separator="true">;</mo><mi>a</mi><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo separator="true">;</mo><msub><mi>b</mi><mn>1</mn></msub><mo separator="true">;</mo><mi>a</mi><mo>=</mo><msub><mi>b</mi><mn>2</mn></msub><mo separator="true">;</mo><mi>a</mi><mo separator="true">;</mo><msub><mi>b</mi><mn>1</mn></msub><mo separator="true">;</mo><mi>a</mi><mo>=</mo><msub><mi>b</mi><mn>2</mn></msub><mo separator="true">;</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo separator="true">;</mo><mi>a</mi><mo>=</mo><msub><mi>b</mi><mn>2</mn></msub><mo separator="true">;</mo><mi>a</mi><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">b_1; a = \mathrm{id}; b_1; a = b_2; a; b_1; a = b_2; \mathrm{id}; a = b_2; a = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>b</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">b_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> の逆射より.</p>
</dd>
</dl>
<p>停止する initial sequence からは,initial algebra を構成できる.</p>
<dl class="docutils">
<dt>補題. (initial algebra の構成)</dt>
<dd><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> で initial sequence が停止する時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">←</mo><mpadded lspace="0.3em" width="+0.6em"><msup><msubsup><mi>f</mi><mrow><mi>α</mi><mo>+</mo><mn>1</mn></mrow><mi>α</mi></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup></mpadded></mover><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F^\alpha 0 \xleftarrow{{f^\alpha_{\alpha + 1}}^{-1}} F (F^\alpha 0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.214em;margin-left:-0.1076em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3455em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMinYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M400000 241H110l3-3c68.7-52.7 113.7-120
135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8
-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247
c-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208
490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3
1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202
l-3-3h399890zM100 241v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span> は initial algebra</p>
<p>証明:</p>
<p>任意の algebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>X</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>a</mi></mpadded></mover><mi>X</mi></mrow><annotation encoding="application/x-tex">F X \xrightarrow{a} X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">FX</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> について,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo>≤</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\beta \leq \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>h</mi><mi>β</mi></msup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">h^\beta: F^\beta 0 \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> を以下のように定義する.</p>
<dl class="docutils">
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\beta = 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span> の時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>h</mi><mn>0</mn></msup><mo>:</mo><mn>0</mn><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">h^0: 0 \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> は initial object の一意射で定める.</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi></mrow><annotation encoding="application/x-tex">\beta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span></span></span></span></span> が極限順序数の時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msup><mi>h</mi><mi>γ</mi></msup><msub><mo stretchy="false">)</mo><mrow><mi>γ</mi><mo><</mo><mi>β</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(h^\gamma)_{\gamma < \beta}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> は cocone になるため,一意射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>h</mi><mi>β</mi></msup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">h^\beta: F^\beta 0 \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> が存在する.これで定める.</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo>=</mo><mi>γ</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\beta = \gamma + 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> と書ける時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>h</mi><mi>β</mi></msup><mo>=</mo><mi>F</mi><msup><mi>h</mi><mi>γ</mi></msup><mo separator="true">;</mo><mi>a</mi></mrow><annotation encoding="application/x-tex">h^\beta = F h^\gamma; a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span></span></span></span></span> で定める.</dd>
</dl>
<p>この時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><msubsup><mi>f</mi><mrow><mi>α</mi><mo>+</mo><mn>1</mn></mrow><mi>α</mi></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><msup><mi>h</mi><mi>α</mi></msup><mo>=</mo><mi>F</mi><msup><mi>h</mi><mi>α</mi></msup><mo separator="true">;</mo><mi>a</mi></mrow><annotation encoding="application/x-tex">{f^\alpha_{\alpha + 1}}^{-1}; h^\alpha = F h^\alpha; a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2049em;vertical-align:-0.3064em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8984em;"><span style="top:-3.1473em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span></span></span></span></span> は容易に確かめられる.よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>h</mi><mi>α</mi></msup><mo>:</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">h^\alpha: F^\alpha 0 \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> は準同型.また,準同型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>:</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">k: F^\alpha 0 \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> について,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo>≤</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\beta \leq \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> について <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>k</mi><mi>β</mi></msup><mo>=</mo><msubsup><mi>f</mi><mi>α</mi><mi>β</mi></msubsup><mo separator="true">;</mo><mi>k</mi></mrow><annotation encoding="application/x-tex">k^\beta = f^\beta_\alpha; k</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span></span> とおくと,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>k</mi><mi>β</mi></msup><mo>=</mo><msup><mi>h</mi><mi>β</mi></msup></mrow><annotation encoding="application/x-tex">k^\beta = h^\beta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span></span></span></span></span> となることは以下のように帰納法で示せる.</p>
<dl class="docutils">
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\beta = 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span> の時</dt>
<dd>initial object の一意性より正しい.</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi></mrow><annotation encoding="application/x-tex">\beta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span></span></span></span></span> が極限順序数の時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msup><mi>h</mi><mi>γ</mi></msup><msub><mo stretchy="false">)</mo><mrow><mi>γ</mi><mo><</mo><mi>β</mi></mrow></msub><mo>=</mo><mo stretchy="false">(</mo><msup><mi>k</mi><mi>γ</mi></msup><msub><mo stretchy="false">)</mo><mrow><mi>γ</mi><mo><</mo><mi>β</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(h^\gamma)_{\gamma < \beta} = (k^\gamma)_{\gamma < \beta}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> であるため,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>k</mi><mi>β</mi></msup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">k^\beta: F^\beta 0 \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> はその cocone への分解射になる.よって,colimit <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn></mrow><annotation encoding="application/x-tex">F^\beta 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span></span></span></span></span> の一意性より正しい.</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo>=</mo><mi>γ</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\beta = \gamma + 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> と書ける時</dt>
<dd><img alt=":math:`k^\beta = f^{\gamma + 1}_\alpha; k = F f^\gamma_\alpha; F k; a`" class="first align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/12/algebraic-compact-functor/algebraic-compact-functor/initial-algebra-from-initial-sequence.png"/>
<p class="last">より,i.h. から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>k</mi><mi>β</mi></msup><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msubsup><mi>f</mi><mi>α</mi><mi>γ</mi></msubsup><mo separator="true">;</mo><mi>k</mi><mo stretchy="false">)</mo><mo separator="true">;</mo><mi>a</mi><mo>=</mo><mi>F</mi><msup><mi>h</mi><mi>γ</mi></msup><mo separator="true">;</mo><mi>a</mi><mo>=</mo><msup><mi>h</mi><mi>β</mi></msup></mrow><annotation encoding="application/x-tex">k^\beta = F (f^\gamma_\alpha; k); a = F h^\gamma; a = h^\beta</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span></span></span></span></span> より正しい.</p>
</dd>
</dl>
<p class="last">よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo>=</mo><msup><mi>k</mi><mi>α</mi></msup><mo>=</mo><msup><mi>h</mi><mi>α</mi></msup></mrow><annotation encoding="application/x-tex">k = k^\alpha = h^\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span></span></span></span></span> より準同型は一意に定まることから,題意は示された.</p>
</dd>
</dl>
<p>双対的に,停止する terminal sequence から terminal coalgebra が構成できる.この具体的な設定としては,例えば <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> が colimit を保存すれば良い.</p>
<dl class="docutils">
<dt>定理. (Adámek's Theorem)</dt>
<dd><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> が colimit を保存する時,同型射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo stretchy="false">)</mo><mo>∼</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn></mrow><annotation encoding="application/x-tex">F (F^\omega 0) \sim F^\omega 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span></span></span></span></span> が存在し,initial algebra</p>
<p>証明:</p>
<p class="last"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo>∼</mo><msub><mo><mrow><mi mathvariant="normal">c</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">m</mi></mrow></mo><mrow><mi>n</mi><mo><</mo><mi>ω</mi></mrow></msub><msup><mi>F</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msup><mn>0</mn><mo>∼</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F^\omega 0 \sim \mathop{\mathrm{colim}}_{n < \omega} F^{n + 1} 0 \sim F (F^\omega 0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9915em;vertical-align:-0.1774em;"></span><span class="mop"><span class="mop"><span class="mord"><span class="mord mathrm">colim</span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2274em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span> より.</p>
</dd>
</dl>
<p>なお,今回は ordinal chain で initial sequence を作っているが,上記の定理は countable chain complete ぐらいで成り立つ.双対的に terminal coalgebra も,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> が limit を保存する時構成できる.さて,ここからが本題.</p>
<p>まず, algebra から coalgebra への準同型射を以下のように定義する.</p>
<dl class="docutils">
<dt>定義. (relational <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-morphism)</dt>
<dd><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>a</mi></mpadded></mover><mi>A</mi></mrow><annotation encoding="application/x-tex">F A \xrightarrow{a} A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> 及び <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-coalgebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>b</mi></mpadded></mover><mi>F</mi><mi>B</mi></mrow><annotation encoding="application/x-tex">B \xrightarrow{b} F B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span></span></span></span></span> について,以下の図式を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo>:</mo><mi>A</mi><mo>→</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">m: A \to B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> を relational <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-morphism と呼ぶ:</p>
<img alt=":math:`a; m; b = F m`" class="last align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/12/algebraic-compact-functor/algebraic-compact-functor/relational-f-morphism.png"/>
</dd>
</dl>
<p>自明な relational morphism として以下のものが考えられる.</p>
<dl class="docutils">
<dt>定義. fixed object</dt>
<dd>圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> の自己関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> を考える.対象 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">A \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> が, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∼</mo><mi>F</mi><mi>A</mi></mrow><annotation encoding="application/x-tex">A \sim F A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span></span></span></span></span> を持つ時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> における fixed object と呼ぶ.</dd>
<dt>系.</dt>
<dd>initial algebra 及び terminal coalgebra は fixed object</dd>
<dt>系.</dt>
<dd>fixed object <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi></mrow><annotation encoding="application/x-tex">A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> において, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo>:</mo><mi>A</mi><mo>→</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">\mathrm{id}: A \to A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> は algebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>A</mi><mo>∼</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">F A \sim A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> から coalgebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∼</mo><mi>F</mi><mi>A</mi></mrow><annotation encoding="application/x-tex">A \sim F A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span></span></span></span></span> への relational morphism</dd>
</dl>
<p>また, initial algebra から terminal coalgebra への relational morphism は一意になる.</p>
<dl class="docutils">
<dt>命題.</dt>
<dd><p class="first">initial <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra から terminal <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-coalgebra への relational morphism は存在して一意.</p>
<p>証明:</p>
<p class="last">terminal <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-coalgebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mo>∼</mo><mi>F</mi><mi>B</mi></mrow><annotation encoding="application/x-tex">B \sim F B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>B</mi><mo>∼</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">F B \sim B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> は algebra より, initial algebra からの準同型射が存在し,これは <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mo>∼</mo><mi>F</mi><mi>B</mi></mrow><annotation encoding="application/x-tex">B \sim F B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span></span></span></span></span> への relational morphism にもなる.また, initial algebra からの relational morphism を持ってくると,それは <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>B</mi><mo>∼</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">F B \sim B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> への準同型射でもあるので,準同型射の一意性から一意になる.</p>
</dd>
</dl>
<p>さて, initial algebra と terminal coalgebra が一致するというのは,つまりその構成 object が同型になるということだが,この時 relational morphism としてその同型射を持ってくることができる.よって,上の relational morphism の一意性から, initial algebra と terminal coalgebra の一致を以下のように言い換えできる.</p>
<dl class="docutils">
<dt>定義. (canonical isomorphic)</dt>
<dd>initial algebra から terminal coalgebra の relational morphism が同型射の時, initial algebra と terminal algebra は canonical isomorphic であるといい,その時の relational morphism を canonical isomorphism と呼ぶ.</dd>
</dl>
<p>ところで,initial sequence と terminal sequence の間には relational morphism を設定できる.</p>
<dl class="docutils">
<dt>定義. (relational morphism from initial sequence to terminal sequence)</dt>
<dd><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">h^\alpha_\alpha: F^\alpha 0 \to F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> を以下のように定義する:</p>
<dl class="docutils">
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\alpha = 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span> の時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mn>0</mn><mn>0</mn></msubsup><mo>:</mo><mn>0</mn><mo>→</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">h^0_0: 0 \to 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0622em;vertical-align:-0.2481em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4519em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> は initial object から terminal object への一意射で定める.</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> が極限順序数の時</dt>
<dd>まず,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>β</mi><mo><</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\beta < \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> を固定したとき,後述する <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>γ</mi><mi>β</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>γ</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">h^\beta_\gamma: F^\beta 0 \to F^\gamma 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2322em;vertical-align:-0.3831em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3831em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> のようなものが考えられ,この時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msubsup><mi>h</mi><mi>γ</mi><mi>β</mi></msubsup><msub><mo stretchy="false">)</mo><mrow><mi>γ</mi><mo><</mo><mi>α</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(h^\beta_\gamma)_{\gamma < \alpha}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2322em;vertical-align:-0.3831em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3831em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2274em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> は cone になり limit <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> への普遍射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>β</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>β</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">h^\beta_\alpha: F^\beta 0 \to F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> が作れる.さらに,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msubsup><mi>h</mi><mi>α</mi><mi>β</mi></msubsup><msub><mo stretchy="false">)</mo><mrow><mi>β</mi><mo><</mo><mi>α</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(h^\beta_\alpha)_{\beta < \alpha}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1352em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span><span class="mrel mtight"><</span><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> は cocone になり colimit <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn></mrow><annotation encoding="application/x-tex">F^\alpha 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span></span></span></span></span> からの普遍射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">h^\alpha_\alpha: F^\alpha 0 \to F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> が作れる.なお,これは作る順序を変えても普遍性より同じ射が作れる.これで定める.</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mi>γ</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\alpha = \gamma + 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> と書ける時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo>=</mo><mi>F</mi><msubsup><mi>h</mi><mi>γ</mi><mi>γ</mi></msubsup></mrow><annotation encoding="application/x-tex">h^\alpha_\alpha = F h^\gamma_\gamma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0775em;vertical-align:-0.3831em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3831em;"><span></span></span></span></span></span></span></span></span></span></span> で定める.</dd>
</dl>
<p>なおこの時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>β</mi><mi>α</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>β</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">h^\alpha_\beta: F^\alpha 0 \to F^\beta 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1137em;vertical-align:-0.4192em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4169em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4192em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> を以下のように定義する.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>β</mi><mi>α</mi></msubsup><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msubsup><mi>f</mi><mi>β</mi><mi>α</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>β</mi><mi>β</mi></msubsup></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>α</mi><mo><</mo><mi>β</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>α</mi><mo>=</mo><mi>β</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>β</mi><mi>α</mi></msubsup></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>α</mi><mo>></mo><mi>β</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
h^\alpha_\beta = \left\{\begin{array}{ll}
f^\alpha_\beta; h^\beta_\beta &(\alpha < \beta) \\
h^\alpha_\alpha &(\alpha = \beta) \\
h^\alpha_\alpha; g^\alpha_\beta &(\alpha > \beta)
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0975em;vertical-align:-0.3831em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3831em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.8636em;vertical-align:-1.6818em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-2.5em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.492em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.016em;width:0.8889em;"><svg height="0.016em" preserveaspectratio="xMinYMin" style="width:0.8889em" viewbox="0 0 888.89 16" width="0.8889em" xmlns="http://www.w3.org/2000/svg"><path d="M384 0 H504 V16 H384z M384 0 H504 V16 H384z"></path></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.016em;width:0.8889em;"><svg height="0.016em" preserveaspectratio="xMinYMin" style="width:0.8889em" viewbox="0 0 888.89 16" width="0.8889em" xmlns="http://www.w3.org/2000/svg"><path d="M384 0 H504 V16 H384z M384 0 H504 V16 H384z"></path></svg></span></span><span style="top:-4.3em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.1818em;"><span style="top:-4.2148em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4169em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4192em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.3987em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4374em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.9374em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.7374em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4169em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05278em;">β</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4192em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.6818em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.1818em;"><span style="top:-4.2148em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mclose">)</span></span></span><span style="top:-2.9374em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mclose">)</span></span></span><span style="top:-1.7374em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.6818em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
</dd>
</dl>
<p>ところで,全ての relational morphism は,initial sequence から terminal sequence への relational morphism に分解できる.</p>
<dl class="docutils">
<dt>命題.</dt>
<dd><p class="first">algebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>a</mi></mpadded></mover><mi>A</mi></mrow><annotation encoding="application/x-tex">F A \xrightarrow{a} A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span>,coalgebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>b</mi></mpadded></mover><mi>F</mi><mi>B</mi></mrow><annotation encoding="application/x-tex">B \xrightarrow{b} F B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span></span></span></span></span> について,relational morphism <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo>:</mo><mi>A</mi><mo>→</mo><mi>B</mi></mrow><annotation encoding="application/x-tex">m: A \to B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> が存在する時,initial algebra の構成の補題と同様の作り方で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>h</mi><mi>α</mi></msup><mo>:</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>→</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">h^\alpha: F^\alpha 0 \to A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> を作成し,双対的に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>h</mi><mi>α</mi></msub><mo>:</mo><mi>B</mi><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">h_\alpha: B \to F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> を作成した時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo>=</mo><msup><mi>h</mi><mi>α</mi></msup><mo separator="true">;</mo><mi>m</mi><mo separator="true">;</mo><msub><mi>h</mi><mi>α</mi></msub></mrow><annotation encoding="application/x-tex">h^\alpha_\alpha = h^\alpha; m; h_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> に関する帰納法で示す.</p>
<dl class="last docutils">
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\alpha = 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span> の時</dt>
<dd>initial object の一意性から正しい.</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> が極限順序数の時</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup></mrow><annotation encoding="application/x-tex">h^\alpha_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> の定義と limit,colimit の一意性,i.h. から正しい.</dd>
<dt><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>=</mo><mi>γ</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\alpha = \gamma + 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> と書ける時</dt>
<dd><p class="first">以下が可換になるので,i.h. から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo>=</mo><mi>F</mi><msubsup><mi>h</mi><mi>γ</mi><mi>γ</mi></msubsup><mo>=</mo><mi>F</mi><msup><mi>h</mi><mi>γ</mi></msup><mo separator="true">;</mo><mi>F</mi><mi>m</mi><mo separator="true">;</mo><mi>F</mi><msub><mi>h</mi><mi>γ</mi></msub><mo>=</mo><msup><mi>h</mi><mi>α</mi></msup><mo separator="true">;</mo><mi>m</mi><mo separator="true">;</mo><msub><mi>h</mi><mi>α</mi></msub></mrow><annotation encoding="application/x-tex">h^\alpha_\alpha = F h^\gamma_\gamma = F h^\gamma; F m; F h_\gamma = h^\alpha; m; h_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0775em;vertical-align:-0.3831em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3831em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9805em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">m</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05556em;">γ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> より正しい.</p>
<img alt=":math:`h^\gamma; m; h_\gamma = f^\gamma_{\gamma + 1}; F h^\gamma; F m; F h_\gamma; g^{\gamma + 1}_\gamma`" class="last align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/12/algebraic-compact-functor/algebraic-compact-functor/ordinal-cond-for-relational-from-ini-to-ter.png"/>
</dd>
</dl>
</dd>
</dl>
<p>ここまでが準備.</p>
</div>
<div class="section" id="algebraically-compact">
<h2>Algebraically Compact<a class="headerlink" href="#algebraically-compact" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>initial algebra と terminal coalgebra が一致するような functor を, algebraically compact と呼ぶ.</p>
<dl class="docutils">
<dt>定義. (algebraically compact functor)</dt>
<dd>圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> に対して,自己関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> が initial <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra と terminal <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra を持ち,canonical isomorphic になる時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> は algebraically compact だと呼ぶ.また,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> が fixed object を持つならば algebraically compact である時,条件付き algebraically compact であると呼ぶ.</dd>
</dl>
<p>ところで, initial algebra や terminal coalgebra は fixed object なので, fixed object がないというのはつまり,関手が initial algebra や terminal coalgebra をそもそも作れる構造を持っていないということになる.つまり,条件付き algebraically compact とは,関手がそもそも initial algebra や terminal coalgebra を持てる構造にある前提で,その一致性があるというものになる.前の系を思い出すと, fixed object があれば relational morphism は作れるので,後重要なのは initial sequence の colimit と terminal sequence の limit が一致するかということになる.なお,自明だが algebraically compact なら条件付き algebraically compact である.</p>
<p>ついでに, category に対してのざっくりとした algebraically compact 性も定められている.</p>
<dl class="docutils">
<dt>定義. (algebraically compact category)</dt>
<dd>圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> に対して,任意の自己関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> が algebraically compact である時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> を algebraically compact と呼ぶ.また,任意の fixed object を持つ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> が algebraically compact である時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> を条件付き algebraically compact であると呼ぶ.</dd>
<dt>定義. (algebraically complete category)</dt>
<dd>圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> に対して,任意の自己関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> が initial <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span>-algebra を持つ時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> を algebraically complete と呼ぶ.</dd>
</dl>
<p>algebraically complete というのは Fleyd が導入した言葉 <a class="footnote-reference" href="#fleyd-1991" id="auto-id-3">[1]</a> .なお,algebraically compact category は algebraically complete category.さて,具体的にどういう条件下だと algebraically compact になるんだろうか? 1つの条件としては,以下のものがある.</p>
<dl class="docutils">
<dt>定理. (algebraically compact の十分条件)</dt>
<dd><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> について,以下を満たす時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> は algebraically compact</p>
<ul class="simple">
<li>ある <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">\alpha_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> が存在して,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>></mo><msub><mi>α</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">\alpha > \alpha_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">h^\alpha_\alpha: F^\alpha 0 \to F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> が同型射</li>
<li>ある algebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>a</mi></mpadded></mover><mi>A</mi></mrow><annotation encoding="application/x-tex">F A \xrightarrow{a} A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> 及び coalgebra <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>b</mi></mpadded></mover><mi>F</mi><mi>B</mi></mrow><annotation encoding="application/x-tex">B \xrightarrow{b} F B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">FB</span></span></span></span></span> の間の relational morphism <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>m</mi></mpadded></mover><mi>B</mi></mrow><annotation encoding="application/x-tex">A \xrightarrow{m} B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></span> が存在する</li>
</ul>
<p>証明:</p>
<p>この時,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>></mo><msub><mi>α</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">\alpha > \alpha_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>h</mi><mi>α</mi></msup><mo separator="true">;</mo><mi>m</mi><mo separator="true">;</mo><msub><mi>h</mi><mi>α</mi></msub><mo>=</mo><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup></mrow><annotation encoding="application/x-tex">h^\alpha; m; h_\alpha = h^\alpha_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> が同型射になる.ここで,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mi>α</mi></msub><mo>=</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>m</mi></mpadded></mover><mi>B</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msub><mi>h</mi><mi>α</mi></msub></mpadded></mover><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msup><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup></mpadded></mover><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msup><mi>h</mi><mi>α</mi></msup></mpadded></mover><mi>A</mi></mrow><annotation encoding="application/x-tex">e_\alpha = A \xrightarrow{m} B \xrightarrow{h_\alpha} F^\alpha 1 \xrightarrow{{h^\alpha_\alpha}^{-1}} F^\alpha 0 \xrightarrow{h^\alpha} A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.214em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.15em;vertical-align:-0.011em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.139em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> を考えると,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mi>α</mi></msub><mo separator="true">;</mo><msub><mi>e</mi><mi>α</mi></msub><mo>=</mo><mi>m</mi><mo separator="true">;</mo><msub><mi>h</mi><mi>α</mi></msub><mo separator="true">;</mo><msup><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><msup><mi>h</mi><mi>α</mi></msup><mo separator="true">;</mo><mi>m</mi><mo separator="true">;</mo><msub><mi>h</mi><mi>α</mi></msub><mo separator="true">;</mo><msup><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><msup><mi>h</mi><mi>α</mi></msup><mo>=</mo><mi>m</mi><mo separator="true">;</mo><msub><mi>h</mi><mi>α</mi></msub><mo separator="true">;</mo><msup><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo separator="true">;</mo><msup><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><msup><mi>h</mi><mi>α</mi></msup><mo>=</mo><mi>m</mi><mo separator="true">;</mo><msub><mi>h</mi><mi>α</mi></msub><mo separator="true">;</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo separator="true">;</mo><msup><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><msup><mi>h</mi><mi>α</mi></msup><mo>=</mo><msub><mi>e</mi><mi>α</mi></msub></mrow><annotation encoding="application/x-tex">
e_\alpha; e_\alpha = m; h_\alpha; {h^\alpha_\alpha}^{-1}; h^\alpha; m; h_\alpha; {h^\alpha_\alpha}^{-1}; h^\alpha = m; h_\alpha; {h^\alpha_\alpha}^{-1}; h^\alpha_\alpha; {h^\alpha_\alpha}^{-1}; h^\alpha = m; h_\alpha; \mathrm{id}; {h^\alpha_\alpha}^{-1}; h^\alpha = e_\alpha
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1654em;vertical-align:-0.247em;"></span><span class="mord mathnormal">m</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9184em;"><span style="top:-3.1673em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9184em;"><span style="top:-3.1673em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1654em;vertical-align:-0.247em;"></span><span class="mord mathnormal">m</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9184em;"><span style="top:-3.1673em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9184em;"><span style="top:-3.1673em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1654em;vertical-align:-0.247em;"></span><span class="mord mathnormal">m</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9184em;"><span style="top:-3.1673em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></div>
<p>を満たす.ところで,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>0</mn></msub><mo><</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha_0 < \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> となる <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> 全体は集合を超えることが知られているので,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>0</mn></msub><mo><</mo><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha_0 < \alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> における <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mi>α</mi></msub></mrow><annotation encoding="application/x-tex">e_\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> 全体が集合になるためには,ある <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>0</mn></msub><mo><</mo><msub><mi>α</mi><mn>1</mn></msub><mo><</mo><msub><mi>α</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">\alpha_0 < \alpha_1 < \alpha_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><msub><mi>α</mi><mn>1</mn></msub></msub><mo>=</mo><msub><mi>e</mi><msub><mi>α</mi><mn>2</mn></msub></msub></mrow><annotation encoding="application/x-tex">e_{\alpha_1} = e_{\alpha_2}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6807em;vertical-align:-0.2501em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2501em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6807em;vertical-align:-0.2501em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2501em;"><span></span></span></span></span></span></span></span></span></span></span> となる必要がある <a class="footnote-reference" href="#term-have-only-a-set" id="auto-id-4">[3]</a> .この時,</p>
<img alt=":math:`h^{\alpha_2}_{\alpha_2}; g^{\alpha_2}_{\alpha_1}; {h^{\alpha_1}_{\alpha_1}}^{-1}; f^{\alpha_1}_{\alpha_2} = h^{\alpha_2}; e_{\alpha_1}; m; h_{\alpha_2}; {h^{\alpha_2}_{\alpha_2}}^{-1} = h^{\alpha_2}; e_{\alpha_2}; m; h_{\alpha_2}; {h^{\alpha_2}_{\alpha_2}}^{-1} = \mathrm{id}`" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/12/algebraic-compact-functor/algebraic-compact-functor/finally-canonical-iso-from-relational-morphism.png"/>
<p class="last">が可換になるので,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msubsup><mi>h</mi><msub><mi>α</mi><mn>2</mn></msub><msub><mi>α</mi><mn>2</mn></msub></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><msub><mi>α</mi><mn>1</mn></msub><msub><mi>α</mi><mn>2</mn></msub></msubsup><mo separator="true">;</mo><msup><msubsup><mi>h</mi><msub><mi>α</mi><mn>1</mn></msub><msub><mi>α</mi><mn>1</mn></msub></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo stretchy="false">)</mo><mo separator="true">;</mo><msubsup><mi>f</mi><msub><mi>α</mi><mn>2</mn></msub><msub><mi>α</mi><mn>1</mn></msub></msubsup><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">(h^{\alpha_2}_{\alpha_2}; g^{\alpha_2}_{\alpha_1}; {h^{\alpha_1}_{\alpha_1}}^{-1}); f^{\alpha_1}_{\alpha_2} = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2455em;vertical-align:-0.3471em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8984em;"><span style="top:-3.1473em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> で,逆も <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><msub><mi>α</mi><mn>2</mn></msub><msub><mi>α</mi><mn>1</mn></msub></msubsup><mo separator="true">;</mo><mo stretchy="false">(</mo><msubsup><mi>h</mi><msub><mi>α</mi><mn>2</mn></msub><msub><mi>α</mi><mn>2</mn></msub></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><msub><mi>α</mi><mn>1</mn></msub><msub><mi>α</mi><mn>2</mn></msub></msubsup><mo separator="true">;</mo><msup><msubsup><mi>h</mi><msub><mi>α</mi><mn>1</mn></msub><msub><mi>α</mi><mn>1</mn></msub></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">f^{\alpha_1}_{\alpha_2}; (h^{\alpha_2}_{\alpha_2}; g^{\alpha_2}_{\alpha_1}; {h^{\alpha_1}_{\alpha_1}}^{-1}) = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2455em;vertical-align:-0.3471em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8984em;"><span style="top:-3.1473em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> が成り立つことが同様に確かめられる.よって,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><msub><mi>α</mi><mn>2</mn></msub><msub><mi>α</mi><mn>1</mn></msub></msubsup></mrow><annotation encoding="application/x-tex">f^{\alpha_1}_{\alpha_2}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0415em;vertical-align:-0.3471em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span></span></span></span></span> は同型射であり,この時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mrow><msub><mi>α</mi><mn>1</mn></msub><mo>+</mo><mn>1</mn></mrow><msub><mi>α</mi><mn>1</mn></msub></msubsup></mrow><annotation encoding="application/x-tex">f^{\alpha_1}_{\alpha_1 + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1127em;vertical-align:-0.3664em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3664em;"><span></span></span></span></span></span></span></span></span></span></span> も同型射.つまり, initial sequence が停止し,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><msub><mi>α</mi><mn>1</mn></msub></msup><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">←</mo><mpadded lspace="0.3em" width="+0.6em"><msup><msubsup><mi>f</mi><mrow><msub><mi>α</mi><mn>1</mn></msub><mo>+</mo><mn>1</mn></mrow><msub><mi>α</mi><mn>1</mn></msub></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup></mpadded></mover><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><msub><mi>α</mi><mn>1</mn></msub></msup><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F^{\alpha_1} 0 \xleftarrow{{f^{\alpha_1}_{\alpha_1 + 1}}^{-1}} F (F^{\alpha_1} 0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.6826em;vertical-align:-0.011em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6716em;"><span style="top:-3.6899em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8664em;"><span style="top:-2.1885em;margin-left:-0.1076em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3448em;margin-left:-0.0037em;margin-right:0.1em;"><span class="pstrut" style="height:2.6444em;"></span><span class="mord mtight">1</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2996em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.0588em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3448em;margin-left:-0.0037em;margin-right:0.1em;"><span class="pstrut" style="height:2.6444em;"></span><span class="mord mtight">1</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2996em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.5255em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9738em;"><span style="top:-3.0135em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMinYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M400000 241H110l3-3c68.7-52.7 113.7-120
135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8
-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247
c-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208
490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3
1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202
l-3-3h399890zM100 241v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span> は initial algebra になる.同様に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><msub><mi>α</mi><mn>1</mn></msub></msup><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msup><msubsup><mi>g</mi><msub><mi>α</mi><mn>1</mn></msub><mrow><msub><mi>α</mi><mn>1</mn></msub><mo>+</mo><mn>1</mn></mrow></msubsup><mrow><mo>−</mo><mn>1</mn></mrow></msup></mpadded></mover><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><msub><mi>α</mi><mn>1</mn></msub></msup><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F^{\alpha_1} 1 \xrightarrow{{g^{\alpha_1 + 1}_{\alpha_1}}^{-1}} F (F^{\alpha_1} 1)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.6826em;vertical-align:-0.011em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6716em;"><span style="top:-3.6716em;"><span class="pstrut" style="height:2.7886em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0191em;"><span style="top:-2.3413em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3448em;margin-left:-0.0037em;margin-right:0.1em;"><span class="pstrut" style="height:2.6444em;"></span><span class="mord mtight">1</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2996em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.0588em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3448em;margin-left:-0.0037em;margin-right:0.1em;"><span class="pstrut" style="height:2.6444em;"></span><span class="mord mtight">1</span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2996em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3728em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.1266em;"><span style="top:-3.1663em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.7776em;"><span class="pstrut" style="height:2.7886em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span> は terminal coalgebra であり,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><msub><mi>α</mi><mn>1</mn></msub><msub><mi>α</mi><mn>1</mn></msub></msubsup></mrow><annotation encoding="application/x-tex">h^{\alpha_1}_{\alpha_1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0415em;vertical-align:-0.3471em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0037em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3471em;"><span></span></span></span></span></span></span></span></span></span></span> は canonical iso になる.</p>
</dd>
</dl>
<p>ところで,ここから条件付き algebraically compact の条件が以下のようになることも分かる.</p>
<dl class="docutils">
<dt>系. (条件付き algebraically compact の十分条件)</dt>
<dd><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> について,以下を満たす時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> は algebraically compact</p>
<ul class="simple">
<li>ある <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">\alpha_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> が存在して,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi><mo>></mo><msub><mi>α</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">\alpha > \alpha_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>α</mi><mi>α</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">h^\alpha_\alpha: F^\alpha 0 \to F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9414em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> が同型射</li>
</ul>
<p>証明:</p>
<p class="last">fixed object の relational morphism が取れるため.</p>
</dd>
</dl>
<p>つまり,ある functor が fixed object を持つ,つまり initial algebra や terminal coalgebra を持てる構造になっていた時, initial sequence から terminal sequence の対応が同型射に落とし込める状況であればいいということになる.</p>
</div>
<div class="section" id="auto-id-5">
<h2>具体例<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>では, initial algebra から terminal coalgebra への対応が同型になる状況は具体的にどういう状況なのかを見ていく.</p>
<dl class="docutils">
<dt>補題.</dt>
<dd><p class="first">CPO enriched な圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> ,自己関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> (CPO enriched とは限らない) において,以下を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msup><mi>F</mi><mi>n</mi></msup><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>l</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup></mpadded></mover><msup><mi>F</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msup><mn>0</mn><msub><mo stretchy="false">)</mo><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(F^n 1 \xrightarrow{l^n_{n + 1}} F^{n + 1} 0)_{n \in \mathbb{N}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.389em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.139em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.214em;margin-left:-0.0197em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3455em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3322em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span></span></span></span></span> が存在するとする:</p>
<img alt=":math:`l^n_{n + 1}: F^n 1 \to F^{n + 1} 0`" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/12/algebraic-compact-functor/algebraic-compact-functor/morphism-from-terminal-to-initial-seq.png"/>
<ul class="simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">n \in \mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> で, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>n</mi><mi>n</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo>=</mo><msubsup><mi>f</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup></mrow><annotation encoding="application/x-tex">h^n_n; l^n_{n + 1} = f^n_{n + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0009em;vertical-align:-0.3064em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0009em;vertical-align:-0.3064em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">n \in \mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> で, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>g</mi><mi>n</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo>⊑</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">g^{n + 1}_n; l^n_{n + 1}; h^{n + 1}_{n + 1} \sqsubseteq \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1789em;vertical-align:-0.3246em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">n \in \mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> で, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>l</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">l^n_{n + 1}; h^{n + 1}_{n + 1}; g^{n + 1}_n = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1789em;vertical-align:-0.3246em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span></li>
</ul>
<p>この時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo>∼</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">F^\omega 0 \sim F^\omega 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span></p>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn></mrow><annotation encoding="application/x-tex">F^\omega 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span></span></span></span></span> が terminal sequence の limit であることを示せば, limit の一意性から言える.まず,cone <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msub><mi>h</mi><mi>n</mi></msub><mo>:</mo><mi>X</mi><mo>→</mo><msup><mi>F</mi><mi>n</mi></msup><mn>1</mn><msub><mo stretchy="false">)</mo><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(h_n: X \to F^n 1)_{n \in \mathbb{N}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3322em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span></span></span></span></span> を取ってきたとき,この cone から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mi>ω</mi></msubsup><mo>:</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo>→</mo><msup><mi>F</mi><mi>n</mi></msup><mn>1</mn><msub><mo stretchy="false">)</mo><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(h^\omega_\omega; g^\omega_n: F^\omega 0 \to F^n 1)_{n \in \mathbb{N}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mord">1</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3322em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span></span></span></span></span> への普遍射が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>h</mi><mi>ω</mi></msub><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow><annotation encoding="application/x-tex">h_\omega = \bigsqcup_{m \in \mathbb{N}} h_m; l^m_{m + 1}; f^{m + 1}_\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1412em;vertical-align:-0.3271em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> であることを示す.</p>
<p>さて,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">n \in \mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> に対して <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>h</mi><mi>ω</mi></msub><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow><annotation encoding="application/x-tex">h_\omega = \bigsqcup_{m > n} h_m; l^m_{m + 1}; f^{m + 1}_\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1412em;vertical-align:-0.3271em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></span> ,つまり <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><msub><mo stretchy="false">)</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(h_m; l^m_{m + 1}; f^{m + 1}_\omega)_{m \in \mathbb{N}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1205em;vertical-align:-0.3064em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3322em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span></span></span></span></span> が単調増加であることを示す.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⊑</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub><mo separator="true">;</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msubsup></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{ll}
h_m; l^m_{m + 1}; f^{m + 1}_\omega
&= h_{m + 1}; g^{m + 1}_m; l^m_{m + 1}; f^{m + 1}_{m + 2}; f^{m + 2}_\omega \\
&= h_{m + 1}; g^{m + 1}_m; l^m_{m + 1}; h^{m + 1}_{m + 1}; l^{m + 1}_{m + 2}; f^{m + 2}_\omega \\
&\sqsubseteq h_{m + 1}; \mathrm{id} ;l^{m + 1}_{m + 2}; f^{m + 2}_\omega \\
&= h_{m + 1}; l^{m + 1}_{m + 2}; f^{m + 2}_\omega
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:4.857em;vertical-align:-2.1785em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6785em;"><span style="top:-4.8242em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-2.3958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.1815em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.1785em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6785em;"><span style="top:-4.8242em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.3958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.1815em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.1785em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>ここから可換性を以下のように示せる:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>h</mi><mi>ω</mi></msub><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mi>ω</mi></msubsup></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">(</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo stretchy="false">)</mo><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mi>ω</mi></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mi>ω</mi></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mi>ω</mi></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mi>m</mi></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mi>m</mi></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msub><mi>h</mi><mi>n</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mi>h</mi><mi>n</mi></msub></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{ll}
h_\omega; h^\omega_\omega; g^\omega_n
&= (\bigsqcup_{m \in \mathbb{N}} h_m; l^m_{m + 1}; f^{m + 1}_\omega); h^\omega_\omega; g^\omega_n \\
&= \bigsqcup_{m > n} h_m; l^m_{m + 1}; f^{m + 1}_\omega; h^\omega_\omega; g^\omega_n \\
&= \bigsqcup_{m > n} h_m; l^m_{m + 1}; h^{m + 1}_\omega; g^\omega_n \\
&= \bigsqcup_{m > n} h_m; l^m_{m + 1}; h^{m + 1}_{m + 1}; g^{m + 1}_n \\
&= \bigsqcup_{m > n} h_m; l^m_{m + 1}; h^{m + 1}_{m + 1}; g^{m + 1}_m; g^m_n \\
&= \bigsqcup_{m > n} h_m; \mathrm{id}; g^m_n \\
&= \bigsqcup_{m > n} h_n \\
&= h_n
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:9.6285em;vertical-align:-4.5642em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.0642em;"><span style="top:-7.2242em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-6.0242em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-4.8242em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-2.3958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.1958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:0.0042em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:1.2042em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.5642em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.0642em;"><span style="top:-7.2242em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-6.0242em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-4.8242em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.3958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.1958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:0.0042em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:1.2042em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.5642em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>さて,分解射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo>:</mo><mi>X</mi><mo>→</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn></mrow><annotation encoding="application/x-tex">h'_\omega: X \to F^\omega 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9989em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span></span></span></span></span> を持ってきた時,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><msub><mi>h</mi><mi>ω</mi></msub></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msub><mi>h</mi><mi>m</mi></msub><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo separator="true">;</mo><mo stretchy="false">(</mo><msub><mo>⨆</mo><mi>m</mi></msub><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{ll}
h_\omega
&= \bigsqcup_{m \in \mathbb{N}} h_m; l^m_{m + 1}; f^{m + 1}_\omega \\
&= \bigsqcup_{m \in \mathbb{N}} h'_\omega; h^\omega_\omega; g^\omega_m; l^m_{m + 1}; f^{m + 1}_\omega \\
&= \bigsqcup_{m \in \mathbb{N}} h'_\omega; h^\omega_\omega; g^\omega_m; l^m_{m + 1}; f^{m + 1}_\omega \\
&= h'_\omega; (\bigsqcup_m h^\omega_\omega; g^\omega_m; l^m_{m + 1}; f^{m + 1}_\omega)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:4.8em;vertical-align:-2.15em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0017em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>となる.ここで,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msubsup><mi>f</mi><mi>ω</mi><mi>n</mi></msubsup><mo separator="true">;</mo><mo stretchy="false">(</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msubsup><mi>f</mi><mi>m</mi><mi>n</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>m</mi><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msubsup><mi>f</mi><mi>m</mi><mi>n</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msubsup><mi>f</mi><mi>ω</mi><mi>n</mi></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msubsup><mi>f</mi><mi>ω</mi><mi>n</mi></msubsup></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{ll}
f^n_\omega; (\bigsqcup_{m \in \mathbb{N}} h^\omega_\omega; g^\omega_m; l^m_{m + 1}; f^{m + 1}_\omega)
&= \bigsqcup_{m > n} f^n_m; h^m_m; l^m_{m + 1}; f^{m + 1}_\omega \\
&= \bigsqcup_{m > n} f^n_m; f^m_{m + 1}; f^{m + 1}_\omega \\
&= \bigsqcup_{m > n} f^n_\omega \\
&= f^n_\omega
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:4.8em;vertical-align:-2.15em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">より, colimit の普遍射の一意性から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">\bigsqcup_{m \in \mathbb{N}} h^\omega_\omega; g^\omega_m; l^m_{m + 1}; f^{m + 1}_\omega = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1412em;vertical-align:-0.3271em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> .よって, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo>=</mo><msub><mi>h</mi><mi>ω</mi></msub></mrow><annotation encoding="application/x-tex">h'_\omega = h_\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9989em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> より普遍射の一意性が示せる.</p>
</dd>
<dt>命題.</dt>
<dd><p class="first">CPO enriched な圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> , order enriched な関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>g</mi><mn>0</mn><mn>1</mn></msubsup></mpadded></mover><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>l</mi></mpadded></mover><mi>F</mi><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>h</mi><mn>1</mn><mn>1</mn></msubsup></mpadded></mover><mi>F</mi><mn>1</mn><mo>⊑</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">T 1 \xrightarrow{g^1_0} 1 \xrightarrow{l} F 0 \xrightarrow{h^1_1} F 1 \sqsubseteq \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.214em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">0</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.214em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi><mo>:</mo><mn>1</mn><mo>→</mo><mi>F</mi><mn>0</mn></mrow><annotation encoding="application/x-tex">l: 1 \to F 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span></span></span></span></span> が与えられた時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo>∼</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">F^\omega 0 \sim F^\omega 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span></p>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>l</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo>=</mo><msup><mi>F</mi><mi>n</mi></msup><mi>l</mi></mrow><annotation encoding="application/x-tex">l^n_{n + 1} = F^n l</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0009em;vertical-align:-0.3064em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span></span></span></span></span> とした時,それが上の補題の条件を満たすことを,数学的帰納法で確認する.</p>
<ul class="last">
<li><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">n = 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span> の時,一意性より <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mn>0</mn></msubsup><mo>=</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">f^0_{n + 1} = \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1205em;vertical-align:-0.3064em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo>:</mo><mn>1</mn><mo>→</mo><mn>1</mn><mo>=</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\mathrm{id}: 1 \to 1 = \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> より成り立つ.</p>
</li>
<li><p class="first"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mi>m</mi></mrow><annotation encoding="application/x-tex">n = m</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span></span> の時成り立つと仮定すると, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mi>m</mi><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">n = m + 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> の時,</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>n</mi><mi>n</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo>=</mo><mi>F</mi><msubsup><mi>h</mi><mi>m</mi><mi>m</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msubsup><mi>h</mi><mi>m</mi><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo stretchy="false">)</mo><mo>=</mo><mi>F</mi><msubsup><mi>f</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo>=</mo><msubsup><mi>f</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup></mrow><annotation encoding="application/x-tex">h^n_n; l^n_{n + 1} = F h^m_m; F l^m_{m + 1} = F (h^m_m; l^m_{m + 1}) = F f^m_{m + 1} = f^n_{n + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0009em;vertical-align:-0.3064em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0009em;vertical-align:-0.3064em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0564em;vertical-align:-0.3064em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0009em;vertical-align:-0.3064em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0009em;vertical-align:-0.3064em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>g</mi><mi>n</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msubsup><mi>g</mi><mi>m</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo stretchy="false">)</mo><mo>⊑</mo><mi>F</mi><mtext> </mtext><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">g^{n + 1}_n; l^n_{n + 1}; h^{n + 1}_{n + 1} = F (g^{m + 1}_m; l^m_{m + 1}; h^{m + 1}_{m + 1}) \sqsubseteq F\, \mathrm{id} = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1789em;vertical-align:-0.3246em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1789em;vertical-align:-0.3246em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>l</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>n</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo stretchy="false">)</mo><mo>=</mo><mi>F</mi><mtext> </mtext><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">l^n_{n + 1}; h^{n + 1}_{n + 1}; g^{n + 1}_n = F (l^m_{m + 1}; h^{m + 1}_{m + 1}; g^{m + 1}_m) = F\, \mathrm{id} = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1789em;vertical-align:-0.3246em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1789em;vertical-align:-0.3246em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span></li>
</ul>
<p>より成り立つ.</p>
</li>
</ul>
</dd>
<dt>定理.</dt>
<dd><p class="first">CPO enriched な圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> , order enriched な関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>g</mi><mn>0</mn><mn>1</mn></msubsup></mpadded></mover><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>l</mi></mpadded></mover><mi>F</mi><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>h</mi><mn>1</mn><mn>1</mn></msubsup></mpadded></mover><mi>F</mi><mn>1</mn><mo>⊑</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">T 1 \xrightarrow{g^1_0} 1 \xrightarrow{l} F 0 \xrightarrow{h^1_1} F 1 \sqsubseteq \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.214em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">0</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.214em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi><mo>:</mo><mn>1</mn><mo>→</mo><mi>F</mi><mn>0</mn></mrow><annotation encoding="application/x-tex">l: 1 \to F 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span></span></span></span></span> が与えられる時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> は条件付き algebraically compact .</p>
<p>証明:</p>
<p class="last">上の命題から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo>∼</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">F^\omega 0 \sim F^\omega 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> より.</p>
</dd>
</dl>
<p>つまり, CPO enriched な状況で, terminal sequence から initial sequence への対応を, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><annotation encoding="application/x-tex">\mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> すれすれにいい感じに作れれば良いという感じ.ところで,この対応は pointed CPO の場合 bottom を持ってくることで作れる.</p>
<dl class="docutils">
<dt>定理.</dt>
<dd><p class="first">pointed CPO enriched な圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span>,order enriched な関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> は条件付き algebraically compact .</p>
<p>証明:</p>
<p class="last"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi><mo>:</mo><mn>1</mn><mo>→</mo><mi>F</mi><mn>0</mn><mo>=</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">l: 1 \to F 0 = \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> で持ってきた時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>g</mi><mn>0</mn><mn>1</mn></msubsup></mpadded></mover><mn>1</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>l</mi></mpadded></mover><mi>F</mi><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>h</mi><mn>1</mn><mn>1</mn></msubsup></mpadded></mover><mi>F</mi><mn>1</mn><mo>=</mo><mi mathvariant="normal">⊥</mi><mo>⊑</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">T 1 \xrightarrow{g^1_0} 1 \xrightarrow{l} F 0 \xrightarrow{h^1_1} F 1 = \bot \sqsubseteq \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.214em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">0</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.214em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> より.</p>
</dd>
</dl>
<p>さて,今圏は initial / terminal object を持ち, chain cocomplete / cochain complete としているが,空でない pointed CPO enriched な圏においては, chain cocomplete であれば null object (initial でも terminal でもある object) の存在を示せる.</p>
<dl class="docutils">
<dt>命題.</dt>
<dd><p class="first">空でない pointed CPO enriched な圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> において,chain cocomplete なら null object が存在する.</p>
<p>証明:</p>
<p>空でないため圏から object <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">A \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> を適当に一つ持ってこれる.この時,以下の chain が作れる:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi mathvariant="normal">⊥</mi></mpadded></mover><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi mathvariant="normal">⊥</mi></mpadded></mover><mo>⋯</mo></mrow><annotation encoding="application/x-tex">
A \xrightarrow{\bot} A \xrightarrow{\bot} \cdots
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.313em;"></span><span class="minner">⋯</span></span></span></span></span></div>
<p>この colimit <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">A_\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を考える.この構成射は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>u</mi></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub><mo>=</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi mathvariant="normal">⊥</mi></mpadded></mover><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msup><mi>u</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub><mo>=</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi mathvariant="normal">⊥</mi></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">A \xrightarrow{u} A_\infty = A \xrightarrow{\bot} A \xrightarrow{u'} A_\infty = A \xrightarrow{\bot} A_\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2125em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2015em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> より,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi><mo>:</mo><mi>A</mi><mo>→</mo><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">\bot: A \to A_\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> になる.任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">X \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi mathvariant="normal">⊥</mi></mpadded></mover><mi>X</mi></mrow><annotation encoding="application/x-tex">A \xrightarrow{\bot} X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> は cocone になる.この時,colimit からの普遍射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">!</mo><mo>:</mo><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">!: A_\infty \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mclose">!</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> が存在する.また, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mo stretchy="false">!</mo><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>:</mo><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">!': A_\infty \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mclose"><span class="mclose">!</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> が存在した時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi mathvariant="normal">⊥</mi></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msup><mo stretchy="false">!</mo><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mpadded></mover><mi>X</mi><mo>=</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi mathvariant="normal">⊥</mi></mpadded></mover><mi>X</mi></mrow><annotation encoding="application/x-tex">A \xrightarrow{\bot} A_\infty \xrightarrow{!'} X = A \xrightarrow{\bot} X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.3515em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2015em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mclose mtight"><span class="mclose mtight">!</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> より分解射になる.この時,colimit の普遍性より <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">!</mo><mo>=</mo><msup><mo stretchy="false">!</mo><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">! = !'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mclose">!</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span></span><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mclose"><span class="mclose">!</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> である.よって, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">A_\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は initial object になる.</p>
<p class="last">また, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mo lspace="0em" rspace="0em" stretchy="false">!</mo></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">X \xrightarrow{!} A_\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mclose mtight">!</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> があった時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mo lspace="0em" rspace="0em" stretchy="false">!</mo></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub><mo>=</mo><mi>X</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mo lspace="0em" rspace="0em" stretchy="false">!</mo></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo>=</mo><mi mathvariant="normal">⊥</mi></mrow></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub><mo>=</mo><mi>X</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi mathvariant="normal">⊥</mi></mpadded></mover><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">X \xrightarrow{!} A_\infty = X \xrightarrow{!} A_\infty \xrightarrow{\mathrm{id} = \bot} A_\infty = X \xrightarrow{\bot} A_\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mclose mtight">!</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mclose mtight">!</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2581em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">id</span></span><span class="mrel mtight">=</span><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight">⊥</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> より,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">X \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> について <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">!</mo><mo>:</mo><mi>X</mi><mo>→</mo><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">!: X \to A_\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mclose">!</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> も一意に存在する.よって, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">A_\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">∞</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は terminal object にもなる.</p>
</dd>
</dl>
<p>よって,空でない pointed CPO enriched な圏であれば, chain cocomplete を仮定するだけで良い.ところで,ここまでは条件付き algebraically compact ,つまり fixed object を持つ関手のみを対象にしてきたが,関手が CPO enriched ,つまり sup も保存するならば algebraically compact であることが言える.</p>
<dl class="docutils">
<dt>定理.</dt>
<dd><p class="first">pointed CPO enriched な圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span>,CPO enriched な関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> について,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> は algebraically compact .</p>
<p>証明:</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi><mo>:</mo><mn>1</mn><mo>→</mo><mi>F</mi><mn>0</mn><mo>=</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">l: 1 \to F 0 = \bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> で持ってきた時,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo>∼</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">F^\omega 0 \sim F^\omega 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span>.ところで,実はこの時 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo>∼</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F^\omega 0 \sim F (F^\omega 0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span> が示せる.これが成り立てば,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn></mrow><annotation encoding="application/x-tex">F^\omega 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span></span></span></span></span> は fixed object になるので,題意が言える.よって,これを示す.これは,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F (F^\omega 0)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span> が</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>f</mi><mn>1</mn><mn>0</mn></msubsup></mpadded></mover><mi>F</mi><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>f</mi><mn>2</mn><mn>1</mn></msubsup></mpadded></mover><mo>⋯</mo><msup><mi>F</mi><mi>n</mi></msup><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msubsup><mi>f</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow><mi>n</mi></msubsup></mpadded></mover><mo>⋯</mo></mrow><annotation encoding="application/x-tex">
0 \xrightarrow{f^0_1} F 0 \xrightarrow{f^1_2} \cdots F^n 0 \xrightarrow{f^n_{n + 1}} \cdots
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.214em;margin-left:-0.1076em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2569em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2459em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.214em;margin-left:-0.1076em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.15em;vertical-align:-0.011em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.139em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7385em;"><span style="top:-2.214em;margin-left:-0.1076em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3455em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.313em;"></span><span class="minner">⋯</span></span></span></span></span></div>
<p>の colimit であることを示せれば,colimit の一意性から言える.</p>
<p>構成射を</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>ω</mi><mrow><mo mathvariant="normal">′</mo><mi>n</mi></mrow></msubsup><mo>:</mo><msup><mi>F</mi><mi>n</mi></msup><mn>0</mn><mo>→</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mn>0</mn><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mo lspace="0em" rspace="0em" stretchy="false">!</mo></mpadded></mover><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>=</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>F</mi><msubsup><mi>f</mi><mi>ω</mi><mi>m</mi></msubsup></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>=</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
f'^n_\omega: F^n 0 \to F (F^\omega 0) = \left\{\begin{array}{ll}
0 \xrightarrow{!} F (F^\omega 0) &(n = 0) \\
F f^m_\omega &(n = m + 1)
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0489em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7144em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.5841em;"><span style="top:-3.5841em;"><span class="pstrut" style="height:3.1081em;"></span><span class="mord"><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mclose mtight">!</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-2.3841em;"><span class="pstrut" style="height:3.1081em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.0841em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.5841em;"><span style="top:-3.5841em;"><span class="pstrut" style="height:3.1081em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-2.3841em;"><span class="pstrut" style="height:3.1081em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.0841em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<p>で作る.cocone <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msub><mi>h</mi><mi>n</mi></msub><mo>:</mo><msup><mi>F</mi><mi>n</mi></msup><mn>0</mn><mo>→</mo><mi>X</mi><msub><mo stretchy="false">)</mo><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(h_n: F^n 0 \to X)_{n \in \mathbb{N}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3322em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span></span></span></span></span> に対して,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>h</mi><mi>ω</mi></msub><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><mi>F</mi><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msub></mrow><annotation encoding="application/x-tex">h_\omega = \bigsqcup_{m \in \mathbb{N}} F h^\omega_\omega; F g^\omega_m; l^{m + 1}_{m + 2}; h_{m + 2}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1813em;vertical-align:-0.3271em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span></span> が普遍射になることを示す.</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">n = 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span> の時, initial object の普遍性より <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>f</mi><mi>ω</mi><mrow><mo mathvariant="normal">′</mo><mn>0</mn></mrow></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mi>ω</mi></msub><mo>=</mo><msub><mi>h</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">f'^0_\omega; h_\omega = h_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0611em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′0</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> になることは良い.<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>></mo><mn>0</mn></mrow><annotation encoding="application/x-tex">n > 0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span> の時,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msubsup><mi>f</mi><mi>ω</mi><mrow><mo mathvariant="normal">′</mo><mi>n</mi></mrow></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mi>ω</mi></msub></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mi>F</mi><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><mo stretchy="false">(</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><mi>F</mi><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><mi>F</mi><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><mi>F</mi><msubsup><mi>f</mi><mi>m</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>h</mi><mi>m</mi><mi>m</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><mi>F</mi><mo stretchy="false">(</mo><msubsup><mi>f</mi><mi>m</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>m</mi><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo stretchy="false">)</mo><mo separator="true">;</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><mi>F</mi><msubsup><mi>f</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msubsup><mi>f</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mi>n</mi></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>></mo><mi>n</mi></mrow></msub><msub><mi>h</mi><mi>n</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mi>h</mi><mi>n</mi></msub></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{ll}
f'^n_\omega; h_\omega
&= F f^{n - 1}_\omega; (\bigsqcup_{m \in \mathbb{N}} F h^\omega_\omega; F g^\omega_m; l^{m + 1}_{m + 2}; h_{m + 2}) \\
&= \bigsqcup_{m \in \mathbb{N}} F f^{n - 1}_\omega; F h^\omega_\omega; F g^\omega_m; l^{m + 1}_{m + 2}; h_{m + 2} \\
&= \bigsqcup_{m > n} F f^{n - 1}_m; F h^m_m; F l^m_{m + 1}; h_{m + 2} \\
&= \bigsqcup_{m > n} F (f^{n - 1}_m; h^m_m; l^m_{m + 1}); h_{m + 2} \\
&= \bigsqcup_{m > n} F f^{n - 1}_{m + 1}; h_{m + 2} \\
&= \bigsqcup_{m > n} f^n_{m + 2}; h_{m + 2} \\
&= \bigsqcup_{m > n} h_n \\
&= h_n
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:9.6427em;vertical-align:-4.5714em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.0714em;"><span style="top:-7.2171em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-6.0029em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-4.8029em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-3.6029em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-2.3886em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.1886em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:0.0114em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:1.2114em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.5714em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.0714em;"><span style="top:-7.2171em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-6.0029em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span><span style="top:-4.8029em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.6029em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.3886em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.1886em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span><span style="top:0.0114em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0777em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">></span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:1.2114em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.5714em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>より,可換になることが示せる.また,分解射 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo>:</mo><mi>F</mi><mo stretchy="false">(</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo stretchy="false">)</mo><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">h'_\omega: F (F^\omega 0) \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9989em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> について,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><msub><mi>h</mi><mi>ω</mi></msub></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><mi>F</mi><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msub><mi>h</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><mi>F</mi><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mo mathvariant="normal">′</mo><mrow><mi>m</mi><mo>+</mo><mn>2</mn></mrow></mrow></msubsup><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">(</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><mi>F</mi><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><mi>F</mi><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo stretchy="false">)</mo><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><mi>F</mi><mo stretchy="false">(</mo><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo stretchy="false">)</mo><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mi>F</mi><mo stretchy="false">(</mo><msub><mo>⨆</mo><mrow><mi>m</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msubsup><mi>h</mi><mi>ω</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>g</mi><mi>m</mi><mi>ω</mi></msubsup><mo separator="true">;</mo><msubsup><mi>l</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo separator="true">;</mo><msubsup><mi>f</mi><mi>ω</mi><mrow><mi>m</mi><mo>+</mo><mn>1</mn></mrow></msubsup><mo stretchy="false">)</mo><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mi>F</mi><mtext> </mtext><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mo separator="true">;</mo><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mo>∵</mo><mtext>colimit の普遍性より</mtext><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><msubsup><mi>h</mi><mi>ω</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{lll}
h_\omega
&= \bigsqcup_{m \in \mathbb{N}} F h^\omega_\omega; F g^\omega_m; l^{m + 1}_{m + 2}; h_{m + 2} \\
&= \bigsqcup_{m \in \mathbb{N}} F h^\omega_\omega; F g^\omega_m; l^{m + 1}_{m + 2}; f'^{m + 2}_\omega; h'_\omega \\
&= (\bigsqcup_{m \in \mathbb{N}} F h^\omega_\omega; F g^\omega_m; F l^m_{m + 1}; F f^{m + 1}_\omega); h'_\omega \\
&= \bigsqcup_{m \in \mathbb{N}} F (h^\omega_\omega; g^\omega_m; l^m_{m + 1}; f^{m + 1}_\omega); h'_\omega \\
&= F (\bigsqcup_{m \in \mathbb{N}} h^\omega_\omega; g^\omega_m; l^m_{m + 1}; f^{m + 1}_\omega); h'_\omega \\
&= F\,\mathrm{id}; h'_\omega &(\because \text{colimit の普遍性より}) \\
&= h'_\omega
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:8.4285em;vertical-align:-3.9642em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.4642em;"><span style="top:-6.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-5.3958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-4.1958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-2.9958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.7958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-0.5958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:0.6042em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.9642em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.4642em;"><span style="top:-6.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span><span style="top:-5.3958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8542em;"><span style="top:-2.4337em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3246em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">2</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-4.1958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">(</span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.9958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.7958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1825em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.4519em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3064em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-0.5958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">id</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:0.6042em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.9642em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-1.5642em;"><span style="top:-0.5958em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mrel amsrm">∵</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord">colimit </span><span class="mord cjk_fallback">の普遍性より</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.7642em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">よって,分解射は一意になる.</p>
</dd>
</dl>
<p>なお,例えば pointed CPO による圏自体は,pointed CPO enriched であり,chain cocomplete なので今回の圏の条件を満たしている.よって,これ上の関手が fixed object を持って continuous function の順序を保存するか,continuous function space の sup を保存すれば,algebraically compact になる.</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>とりあえず,関手が algebraically compact,つまり initial algebra と terminal algebra が iso になるには,</p>
<ul class="simple">
<li>どこかの <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>α</mi></mrow><annotation encoding="application/x-tex">\alpha</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span></span> で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>α</mi></msup><mn>0</mn><mo>∼</mo><msup><mi>F</mi><mi>α</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">F^\alpha 0 \sim F^\alpha 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> になること</li>
<li>なんらかの algebra と coalgebra の間に relational morphism が作れること</li>
</ul>
<p>が重要で,relational morphism の方は fixed object があれば作れるので,重要なのは initial sequence と terminal sequence がどこかで iso になるかということになる.</p>
<p>さらに, pointed CPO enriched な場合は,関手が order を保存すれば <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> からいい感じに <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>F</mi><mi>ω</mi></msup><mn>0</mn><mo>∼</mo><msup><mi>F</mi><mi>ω</mi></msup><mn>1</mn></mrow><annotation encoding="application/x-tex">F^\omega 0 \sim F^\omega 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∼</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span></span></span></span><span class="mord">1</span></span></span></span></span> に繋げるような terminal sequence から initial sequence への射の列が作れる.なので, order を保存するぐらいで algebraically compact になる.</p>
<p>なるほどなという感じ (こなみ).</p>
<table class="docutils footnote" frame="void" id="fleyd-1991" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[1]</a></td><td><a class="reference external" href="https://link.springer.com/chapter/10.1007/BFb0084215">https://link.springer.com/chapter/10.1007/BFb0084215</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-split-mono-and-split-epi" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td>なお,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>b</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">b_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を持つことを <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> は split monomorphism である,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>b</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">b_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を持つことを <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> は split epimorphism であるという.この命題はもう少し条件を弱め,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> が mono かつ split epi,または epi かつ split mono でも成立する.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="term-have-only-a-set" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[3]</a></td><td>これを, <em>an object has only a set of endomorphisms</em> と元論文で言ってる.最初のこの文の意味が分からなくって, <a class="reference external" href="https://twitter.com/Ziphil/status/1206575467672690688">https://twitter.com/Ziphil/status/1206575467672690688</a> で教えてもらった. Ziphil さん,ありがとうございました.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/12/algebraic-compact-functor.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/12/algebraic-compact-functor.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>多相関数を第一級で取り扱う2019-12-06T16:14:55+09:002022-03-26T15:06:31+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-12-06:/blog/posts/2019/12/rankntypes-a-ghc-extension/<p>今回は,GHC拡張の一つ <tt class="docutils literal">RankNTypes</tt> の紹介をしようと思う.もうちょっとちゃんとまとめたのをいつか Haskell-jp かどっかに投稿したいと思ってる …</p><p>今回は,GHC拡張の一つ <tt class="docutils literal">RankNTypes</tt> の紹介をしようと思う.もうちょっとちゃんとまとめたのをいつか Haskell-jp かどっかに投稿したいと思ってるんだが,時間が (さっさと書け).</p>
<p>さて, Haskell のプログラミングにおいて多相関数はかなり重要な役割を持つ.しかしながら,標準の範囲では多相関数自体を第一級の値として扱うことはできない.私たちに許されるのは,多相関数を定義することだけだ.まあ,それだけでもかなり有用なんだけど,多相関数を第一級で扱えると,色々プログラミングの幅が広がる.今回は,多相関数を第一級として扱うというのはどういうことか,そしてそれをするにはどうすればいいか,そうすることで何がうれしいのかを簡単に触れられたらと思っている.</p>
<div class="section" id="auto-id-2">
<h2>多相関数を第一級で扱うとはどういうことか<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>(パラメトリック)多相関数 ((parametric) polymorphic function,generic function) とは,型の一部にパラメータを含み,そのパラメータにどのような型がきても関数として同じ動作を行うような関数のことだ.といっても,何か特別な技巧を知っていないと扱えない何かというわけではなく,Haskell を触っている人なら日常茶飯事的に扱っている.具体的な例として,以下の関数がそうだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">append</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="nf">append</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">ys</span>
<span class="nf">append</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">append</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">append</tt> はリストを2つ受け取ってリストを返すわけだけど,リストの要素についてはパラメータ化されており,すべてのリストの要素の型が同じ型であること以外は特に制限をつけていない.実際に使う場合には,この要素の型は使う側で決めることができる.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">append</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
</pre></div></td></tr></table></div>
<p>とした場合は,型推論によりパラメータ <tt class="docutils literal">a</tt> に <tt class="docutils literal">Int</tt> 型が割り当てられ,上の式中の <tt class="docutils literal">append</tt> は <tt class="docutils literal">[Int] <span class="pre">-></span> [Int] <span class="pre">-></span> [Int]</tt> という型を持つようになる.このように,パラメータが一切存在しない関数は,多相関数と対比して単相関数 (monomorphic function) と呼ばれる.使う場合にパラメータ <tt class="docutils literal">a</tt> に別のパラメータが割り当てられることもある.例えば以下の場合を考えてみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">b</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">b</span><span class="p">]</span>
<span class="nf">f</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">append</span><span class="w"> </span><span class="p">[</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="n">xs</span><span class="p">]</span>
</pre></div></td></tr></table></div>
<p>この場合, <tt class="docutils literal">append</tt> のパラメータ <tt class="docutils literal">a</tt> には <tt class="docutils literal">f</tt> のパラメータ <tt class="docutils literal">b</tt> が割り当てられ, <tt class="docutils literal">append :: [b] <span class="pre">-></span> [b] <span class="pre">-></span> [b]</tt> という型になる.なお,多相関数はどのような型に対しても成り立つ必要があるので,次のようなものは多相関数にはならず型検査が失敗する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>これは <tt class="docutils literal">a</tt> が <tt class="docutils literal">Int</tt> の場合は大丈夫だが, <tt class="docutils literal">Bool</tt> などの場合はだめだ.どのような型 <tt class="docutils literal">a</tt> でも <tt class="docutils literal">a <span class="pre">-></span> Int</tt> が成り立つというのが多相関数型 <tt class="docutils literal">a <span class="pre">-></span> Int</tt> の意味で,つまりは <tt class="docutils literal">a</tt> が <tt class="docutils literal">Bool</tt> 型の場合でも成り立たなければならないが,実際はそうではない.よって型検査に失敗するわけだ.つまり,多相関数はあくまで <strong>任意の</strong> パラメータに対して指定した型が成り立つものであって,指定した型が成り立つパラメータが <strong>存在する関数ではない</strong> ということには注意してほしい <a class="footnote-reference" href="#existential-types" id="auto-id-3">[1]</a>.多相関数は実際に引数にどういう型を持つ値が来るか特定できないため,通常の関数と比べると実装には工夫が必要になる.多相関数を実行時にどういう表現で持つかは,プログラミング言語それぞれで色々手法があるが,主に</p>
<dl class="docutils">
<dt>テンプレート方式</dt>
<dd>多相関数のパラメータが全て何らかの型が割り当てられ,単相になるような使われ方をしている箇所で,その型に対して一つ関数の実体を作る.</dd>
<dt>型消去方式</dt>
<dd>多相的な値に対して,実行の動作に必要なメタ情報を追加したデータ型を一つ割り当て,コンパイル時型からメタ情報を作成し,多相関数にはメタ情報を付与した値を渡し,それを扱える操作を組み込む.</dd>
</dl>
<p>の二種類がある.GC 付きの言語では, GC のフラグなども値にメタ情報として付与しなければならないため,そこに幾つかメタ情報を追加するだけで対応できる型消去方式と相性が良い.逆に C++ や Rust などではテンプレート方式が使われている.GHC でも型消去方式が主に使われている <a class="footnote-reference" href="#notice-inlining" id="auto-id-4">[2]</a> .</p>
<p>ところで,引数に多相関数を受け取るという指定を書けないのだろうか? 例えば,先ほどの <tt class="docutils literal">append</tt> は共通の型の要素を持つリストであれば,どんな二つを受け取っても動作するわけだ.しかも型消去方式であれば,多相関数に対する実体は,メタ情報などを取り扱うルーチンは組み込まれているものの,一つの関数表現であるはずだ.つまり,以下のような関数が書けてもおかしくないとは思えないだろうか?</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">type</span><span class="w"> </span><span class="kt">Append</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Append</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">([</span><span class="kt">Int</span><span class="p">],</span><span class="w"> </span><span class="p">[</span><span class="kt">Char</span><span class="p">])</span>
<span class="nf">f</span><span class="w"> </span><span class="n">ap</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">ap</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">ap</span><span class="w"> </span><span class="p">[</span><span class="sc">'a'</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="sc">'b'</span><span class="p">])</span>
<span class="nf">appendInts</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span>
<span class="nf">appendInts</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">append</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span>
<span class="nf">append</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="nf">append</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="c1">-- valid: f append</span>
<span class="c1">-- invalid: f appendInts</span>
</pre></div></td></tr></table></div>
<p>ここで, <tt class="docutils literal">f</tt> は <tt class="docutils literal">[a] <span class="pre">-></span> [a] <span class="pre">-></span> [a]</tt> 型を持つ多相関数,つまりどれか一つの型でこのような形をしているのではなく,どのような型 <tt class="docutils literal">T</tt> に対しても <tt class="docutils literal">[T] <span class="pre">-></span> [T] <span class="pre">-></span> [T]</tt> の演算ができる関数を要請している.そして,中では一方で <tt class="docutils literal">a</tt> を <tt class="docutils literal">Int</tt> に割り当てて使用し,もう一方で <tt class="docutils literal">a</tt> を <tt class="docutils literal">Char</tt> に割り当てて使用している.この考え方でいうと, <tt class="docutils literal">appendInts</tt> は失格で, <tt class="docutils literal">Int</tt> のリストしか処理できないため <tt class="docutils literal">f</tt> に渡せてほしくない.</p>
<p>このような関数 <tt class="docutils literal">f</tt> を書くことは可能だろうか? 残念ながら標準の Haskell の範囲ではこのようなことは実現できない <a class="footnote-reference" href="#using-type-class-for-polymorphic-representation" id="auto-id-5">[3]</a> .もしかしたら,以下のように <tt class="docutils literal">f</tt> に型付けをすればいいのではないかと思う人がいるかもしれない:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">([</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">])</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">([</span><span class="kt">Int</span><span class="p">],</span><span class="w"> </span><span class="p">[</span><span class="kt">Char</span><span class="p">])</span>
<span class="nf">f</span><span class="w"> </span><span class="n">ap</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">ap</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">ap</span><span class="w"> </span><span class="p">[</span><span class="sc">'a'</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="sc">'b'</span><span class="p">])</span>
</pre></div></td></tr></table></div>
<p>この関数は型検査が通らないうえに,まるで先ほどの関数と意味が違うものになってしまう.この関数の意味は,どのような型 <tt class="docutils literal">a</tt> を持ってきても,<strong>その型に対する</strong> リストの結合ができる <strong>関数</strong> を受け取って,値を返せる関数だ.つまり受け取るものは単相関数でもいいわけだ.だが,元々の <tt class="docutils literal">f</tt> は <strong>どのような型に対しても</strong> リストの結合ができる <strong>多相関数</strong> を受け取りたいわけだ.つまり,前者は <tt class="docutils literal">f appendInts</tt> という呼び出しでも全然構わなくて,その場合 <tt class="docutils literal">a</tt> に <tt class="docutils literal">Int</tt> が割り当てられるだけなわけだが,後者,つまり元々想定していたものは <tt class="docutils literal">f appendInts</tt> は許容したくないわけだ.</p>
<p>さて,多相関数を受け取る関数を書くことは標準ではできないわけだが,実際問題としてこのようなことができると何がうれしいのだろうか? 実はかなり嬉しいことがあるのだが,ここではその一例を紹介する.より豊富な応用例の紹介は,後の節に譲る.例えば,以下のデータ型に対して,そのデータ型を文字列表現で分かりやすく表示する関数を作ることを考える:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">A</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DInt</span><span class="w"> </span><span class="kt">Int</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">DBool</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">DNode</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kt">A</span>
</pre></div></td></tr></table></div>
<p>単純には <tt class="docutils literal">Show</tt> のインスタンスを作ればいいわけだが,ここでは <tt class="docutils literal">Int</tt> や <tt class="docutils literal">Bool</tt> の表現は切り替え可能にしたいとする.この時に,多相関数を受け取る関数が書ければ,以下のようなことができる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">type</span><span class="w"> </span><span class="kt">PolyShow</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Show</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">String</span>
<span class="nf">showA</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">PolyShow</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">String</span>
<span class="nf">showA</span><span class="w"> </span><span class="n">pshow</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">DInt</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="s">"DInt "</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">pshow</span><span class="w"> </span><span class="n">i</span>
<span class="w"> </span><span class="kt">DBool</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="s">"DBool "</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">pshow</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="kt">DNode</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="s">"DNode ("</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="s">") ("</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="s">")"</span>
<span class="c1">-- >>> d = DNode (DInt 0) (DBool True))</span>
<span class="c1">-- >>> showA show d == "DNode (DInt 0) (DBool True)"</span>
<span class="c1">-- >>> showA (\x -> "(" ++ show x ++ ")") d == "DNode (DInt (0)) (DBool (True))"</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">showA</tt> は,パラメータに割り当てられる型が <tt class="docutils literal">Show</tt> のインスタンスであると制限を付けた多相関数を受け取ることで, <tt class="docutils literal">DInt</tt> や <tt class="docutils literal">DBool</tt> の中身に関して表示を切り替える自由を許している.そして,実際の実行例として上げているものは,一つはそのまま <tt class="docutils literal">show</tt> を使って表示しており,もう一つは <tt class="docutils literal">Int</tt> や <tt class="docutils literal">Bool</tt> の値についても <tt class="docutils literal">()</tt> で挟んで表示するようにしている.こうすることで,表示に対してのパースがより簡単になる.多相関数を受け取る関数を書けない標準の Haskell では, <tt class="docutils literal">Int</tt> や <tt class="docutils literal">Bool</tt> それぞれで関数を引数として受け取らなければならない <a class="footnote-reference" href="#implement-pshow-using-type-class" id="auto-id-6">[4]</a> .今回は二種類だからいいが,もっと末端の型が増えればその分引数が膨れ上がっていくことになる.また,今回の例でいえば,同じ関数を引数分書くことになり,かなりボイラープレートが増えるだろう.これらは,上のように多相関数を受け取れるようになれば解決できるわけだ.</p>
</div>
<div class="section" id="rankntypes">
<h2>RankNTypes<a class="headerlink" href="#rankntypes" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで, Haskell 標準では多相関数を受け取る関数は書けなかったわけだが,我らが GHC にはそれを可能にする拡張がある.それが, <tt class="docutils literal">RankNTypes</tt> だ.具体的なシンタックスとして,一番最初の多相的な <tt class="docutils literal">append</tt> を受け取る関数は,以下のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">type</span><span class="w"> </span><span class="kt">Append</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Append</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">([</span><span class="kt">Int</span><span class="p">],</span><span class="w"> </span><span class="p">[</span><span class="kt">Char</span><span class="p">])</span>
<span class="nf">f</span><span class="w"> </span><span class="n">ap</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">ap</span><span class="w"> </span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">ap</span><span class="w"> </span><span class="p">[</span><span class="sc">'a'</span><span class="p">]</span><span class="w"> </span><span class="p">[</span><span class="sc">'b'</span><span class="p">])</span>
</pre></div></td></tr></table></div>
<p>なお,直接 <tt class="docutils literal">f :: (forall a. [a] <span class="pre">-></span> [a] <span class="pre">-></span> [a]) <span class="pre">-></span> ([Int], [Char])</tt> と書いてもよい.これは,かなり直感的な型表記だと思う.そのままの意味で, <tt class="docutils literal">Append</tt> 型は「どのような型 <tt class="docutils literal">a</tt> を持ってきても, <tt class="docutils literal">[a] <span class="pre">-></span> [a] <span class="pre">-></span> [a]</tt> が成り立つ型」と言っている.なお,この拡張下では以下のような表記も書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">append</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="nf">append</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">ys</span>
<span class="nf">append</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="n">ys</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kt">:</span><span class="w"> </span><span class="n">append</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">ys</span>
</pre></div></td></tr></table></div>
<p>なお,この拡張下でも標準と同じく <tt class="docutils literal">forall a.</tt> の部分は省略してもよいわけだが,こう書くとより <tt class="docutils literal">append</tt> が多相関数でパラメータ <tt class="docutils literal">a</tt> を使用していることが直感的に分かりやすいだろう. <tt class="docutils literal">forall</tt> の後に型制約を書くことも可能なので, <tt class="docutils literal">showA</tt> についてもこの拡張下では実現できる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">type</span><span class="w"> </span><span class="kt">PolyShow</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="kt">Show</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">String</span>
<span class="nf">showA</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">PolyShow</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">String</span>
<span class="nf">showA</span><span class="w"> </span><span class="n">pshow</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">DInt</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="s">"DInt "</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">pshow</span><span class="w"> </span><span class="n">i</span>
<span class="w"> </span><span class="kt">DBool</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="s">"DBool "</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">pshow</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="kt">DNode</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="s">"DNode ("</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="s">") ("</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="s">")"</span>
</pre></div></td></tr></table></div>
<p>これはコンパイルが通るようになる.また,この拡張下ではデータ型に多相関数を格納することも可能だ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">WrapId</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">WrapId</span><span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">WrapId</tt> は多相関数,つまりどんな <tt class="docutils literal">a</tt> に対しても <tt class="docutils literal">a <span class="pre">-></span> a</tt> が成り立つ関数しか受け取れないため, <tt class="docutils literal">WrapId (not :: Bool <span class="pre">-></span> Bool)</tt> みたいな特定の型のみで <tt class="docutils literal">a <span class="pre">-></span> a</tt> の形になるものは型検査が通らないことに注意だ.</p>
<p>なお, <tt class="docutils literal">RankNTypes</tt> の単語の意味だが,元々の概念として,</p>
<ul class="simple">
<li>単相型を rank-0</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><msub><mi>σ</mi><mi>n</mi></msub><mo>∣</mo><msub><mi>σ</mi><mi>n</mi></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>σ</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub><mo>∣</mo><mrow><mtext mathvariant="monospace">forall</mtext><mtext> </mtext><mtext mathvariant="monospace">a.</mtext></mrow><mtext> </mtext><msub><mi>σ</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">\sigma_{n + 1} \mathrel{::=} \sigma_n \mid \sigma_n \mathrel{\text{\texttt{->}}} \sigma_{n + 1} \mid \text{\texttt{forall a.}}\, \sigma_{n + 1}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6389em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord text"><span class="mord texttt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8194em;vertical-align:-0.2083em;"></span><span class="mord text"><span class="mord text"><span class="mord texttt">forall a.</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span></span> を満たす型,つまり関数型の引数部分に rank を一減らした型を指定していいという型を rank-<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(n + 1)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>と呼ぶ型システムがあり,通常の Haskell の範囲では rank-1 までしか使えないが,それを任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> に対して rank-<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> の型が扱えるようにするという意味で命名されている.ただ,この意味が分かりにくいので「arbitary rank types (任意のランクの型)」という名称が一般的には用いられている.この拡張下では,任意の位置で多相関数を受け取れ,また多相関数を受け取って何かをするような多相関数すら受け取れるので,多相関数を通常の関数と同じように扱うことができる <a class="footnote-reference" href="#notice-rankntypes-restriction" id="auto-id-7">[5]</a> .</p>
</div>
<div class="section" id="auto-id-8">
<h2>RankNTypes の応用<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal">RankNTypes</tt> の強みの一つとして,上の例のように違う型に対する処理を一つにまとめて提供できるというものがある.これは事実上型クラスがやっていることでもあるのだが,それを一々型クラスを作らなくても自然な形でプログラミングできるのが,強みと言えるだろう.前挙げた例以外でも,例えば Http サーバを作ることを考えてみた時に,リクエストの型によらずに実装できる部分は多い.具体的には,エラーが起きた時に 500 エラーレスポンスを返す際は,リクエストに対して特に言及をしなくてよいはずだ.ただ, 500 を返すか,それとも 503 などを返したい場合などもあるのかを,ユーザに委ねたい場合もあるはずだ.その場合に,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE BlockArguments #-}</span>
<span class="nf">server</span>
<span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">req</span><span class="o">.</span><span class="w"> </span><span class="n">req</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="p">(</span><span class="kt">Request</span><span class="w"> </span><span class="n">req</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="p">(</span><span class="kt">Response</span><span class="w"> </span><span class="n">req</span><span class="p">))</span>
<span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Request</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="p">(</span><span class="kt">Response</span><span class="w"> </span><span class="kt">Request</span><span class="p">)</span>
<span class="nf">server</span><span class="w"> </span><span class="n">handle</span><span class="w"> </span><span class="n">req</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">handle</span><span class="w"> </span><span class="n">req</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="o">...</span>
</pre></div></td></tr></table></div>
<p>などにしておくと,この関数をテストしたい場合に <tt class="docutils literal">Request</tt> を簡易的なものにした <tt class="docutils literal">TestRequest</tt> 型を使うようにしておいても,同じユーザから渡された関数で処理のエミュレートができるだろう.もし, <tt class="docutils literal">RankNTypes</tt> がない場合は <tt class="docutils literal">Request</tt> と <tt class="docutils literal">TestRequest</tt> 両方に対して関数を定義してもらわなければならないが,それが解決できるわけだ.ところで,これはモジュラリティにも貢献している.ユーザはエラーを処理する関数において,実際のリクエストに対して触れることができない.つまり,ある程度できることが制限できるわけだ.そして, <tt class="docutils literal">Request</tt> 型の実装とは独立に,エラー処理関数の実装が行えたことを型システムで保証できるわけだ.</p>
<p>一般に, <tt class="docutils literal">RankNTypes</tt> はある種のモジュラリティを保証するために使用することもできる.その利用例として有名なのが ST モナドだ. ST モナドは破壊的変更を伴った操作をプログラム中で書くことができ,しかもそれを純粋な世界に紐とく関数 <tt class="docutils literal">runST :: (forall s. ST s a) <span class="pre">-></span> a</tt> が提供されている.ただ, ST モナドはなんでも操作を許容しているわけではなく,配列操作やリファレンスをいじる操作のみを ST モナドの <tt class="docutils literal">s</tt> に言及した多相関数として定義しており,必ず破壊的な操作にはパラメータ <tt class="docutils literal">s</tt> が多相的なまま残るようになっている.そして, <tt class="docutils literal">runST</tt> はその多相的なまま残った <tt class="docutils literal">s</tt> に対して, <tt class="docutils literal">s</tt> によらずに <tt class="docutils literal">a</tt> の型が決まるならば <tt class="docutils literal">ST s</tt> を外せることにしている.そして, <tt class="docutils literal">s</tt> によらずに <tt class="docutils literal">a</tt> の型が決まる場合に,破壊的操作で生まれた配列のインスタンスやリファレンスが実行時にどのような実体を持っていようとも,結果が決定的になることを保証できるよう, API がうまく設計されている.このより詳細な解説は,「<a class="reference external" href="https://shinharad.hateblo.jp/entry/2019/12/04/000050">STモナドはなぜ変更可能な参照を外へ持ち出せないのか調べてみた</a>」で行われているので,ぜひ参照してほしい.一般に,このような API 設計による型安全なメモリ管理の仕組みを実現する方法は, monadic region という名前で知られている.興味があれば,そちらも調べてみてほしい.</p>
<p><tt class="docutils literal">RankNTypes</tt> のもう少し別の応用として,中間データ構造を削減するための手法が知られている.例えば,リストは GHC では融合変換により,自動的にいい感じに関数合成の中間で生まれたデータが削減されるわけだが,それを明示的に <tt class="docutils literal">RankNTypes</tt> で模倣することができる.整数のリストを例にとってみよう.まず,整数リストを以下のように表現する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">IList</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IList</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">unIList</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">r</span><span class="o">.</span><span class="w"> </span><span class="p">(</span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>この表現に対して,通常のリストの相互変換が以下のように定義できる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE BlockArguments #-}</span>
<span class="nf">toList</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IList</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span>
<span class="nf">toList</span><span class="w"> </span><span class="p">(</span><span class="kt">IList</span><span class="w"> </span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="p">(</span><span class="kt">:</span><span class="p">)</span><span class="w"> </span><span class="kt">[]</span>
<span class="nf">fromList</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IList</span>
<span class="nf">fromList</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IList</span><span class="w"> </span><span class="nf">\</span><span class="n">c</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">xs</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="kt">Int</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">n</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">(</span><span class="n">go</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">xs</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>このリストに対して,次のような <tt class="docutils literal">map</tt> を提供する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">map</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Int</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IList</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IList</span>
<span class="nf">map</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="kt">IList</span><span class="w"> </span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IList</span><span class="w"> </span><span class="nf">\</span><span class="n">c</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="n">r</span><span class="p">)</span><span class="w"> </span><span class="n">n</span>
</pre></div></td></tr></table></div>
<p>ちょっと読みにくいが,この関数は,上の相互変換において,元のリストの <tt class="docutils literal">map</tt> と同じ相当の操作を行える.詳しいことは説明しないが,ここで重要なのは,どこにもコンストラクタが現れていないということだ.本来 <tt class="docutils literal">map</tt> ではコンストラクタのパターンマッチによる分解と,コンストラクタを新たに付与する操作が必要だったわけだが,この <tt class="docutils literal">map</tt> ではそのような操作は必要ない.これはいわばイテレータによる <tt class="docutils literal">map</tt> で, <tt class="docutils literal">IList</tt> は <tt class="docutils literal">[Int]</tt> のイテレータ表現と言うとしっくりくる人がいるかもしれない.とにかく,この <tt class="docutils literal">map</tt> を並べて使うと,通常のリストを融合変換下で通常の <tt class="docutils literal">map</tt> を並べるのとそう変わらない効率で使うことができる.このように <tt class="docutils literal">RankNTypes</tt> による連続処理で中間構造生成を必要としない表現へのエンコードは,リスト以外でも研究されている.興味があれば,調べてみてほしい <a class="footnote-reference" href="#kan-extensions-for-optimization" id="auto-id-9">[6]</a>.</p>
</div>
<div class="section" id="advanced-topics">
<h2>Advanced Topics<a class="headerlink" href="#advanced-topics" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,これまで <tt class="docutils literal">RankNTypes</tt> は多相関数を第一級として扱えると紹介してきたわけだが,実は話はそう簡単ではなく,この拡張は幾つかの点でそれを逸脱している.最後にそれにさっと触れて終わろうと思う.</p>
<p>まず, <tt class="docutils literal">RankNTypes</tt> を使うと次のような関数を書くことができる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">giveInt</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">B</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">B</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="p">(</span><span class="kt">A</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">r</span>
</pre></div></td></tr></table></div>
<p>この関数 <tt class="docutils literal">f</tt> が言っていることは,</p>
<ol class="arabic simple">
<li><tt class="docutils literal">B</tt> のインスタンスがあるときに,</li>
<li><tt class="docutils literal">A Int</tt> のインスタンスがあるとき <tt class="docutils literal">Int</tt> の値を返せる関数を受け取って,</li>
<li>その関数は今, <tt class="docutils literal">B</tt> のインスタンスから <tt class="docutils literal">A Int</tt> のインスタンスを導けるはずなので,</li>
<li>そこから <tt class="docutils literal">Int</tt> の値を返せる</li>
</ol>
<p>ということだ.ただ,現実問題として <tt class="docutils literal">A Int</tt> のインスタンスは存在せず, <tt class="docutils literal">B</tt> のインスタンスもないため,この関数は無意味ということにはなる.もちろん,他のモジュールで orphan インスタンスがあればこの関数を実行することはできるわけだが,正直あまり有用なようには見えないだろう.このような関数が有用な場面はあるんだが,この記事の内容から少し逸脱するので,興味があれば調べてみて欲しい <a class="footnote-reference" href="#constraints-package" id="auto-id-10">[7]</a> .とりあえず,ここで言いたいことは,以上の関数が <tt class="docutils literal">RankNTypes</tt> を有効にすると書けるようになるということだ.では,なぜ <tt class="docutils literal">RankNTypes</tt> を有効にすると,このようなものが書けるようになっているのだろう?実は上の関数は,この特別な機能なしでも容易にシュミレートできる.以下のようにだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">B</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">~</span><span class="w"> </span><span class="kt">Int</span><span class="p">,</span><span class="w"> </span><span class="kt">A</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">f</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">r</span>
</pre></div></td></tr></table></div>
<p>そう,多相的なものに type equality で制約を適当に入れてやることで,実現できる.上の表記はこのエイリアスで,簡単に書けるようにしたものと思ってもらってもいい.なので,厳密には <tt class="docutils literal">RankNTypes</tt> とは arbitary rank types + 上のことを書くための便利な簡易構文を追加する拡張と言った方が正確だろう.</p>
<p>上のは単に <tt class="docutils literal">RankNTypes</tt> はおまけもついてるよという話なのだが,もう一つ致命的な注意点がある.それは, <tt class="docutils literal">RankNTypes</tt> でも以下のようなプログラムは書けないということだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span><span class="p">,</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">const</span><span class="w"> </span><span class="kt">True</span><span class="p">,</span><span class="w"> </span><span class="n">const</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>これは, <tt class="docutils literal">forall a. a <span class="pre">-></span> a</tt> 型の多相関数のリストを作ろうというプログラムだ.やってることは,そう複雑ではなさそうだが, GHC ではこのプログラムを <tt class="docutils literal">RankNTypes</tt> 下でコンパイルすることはできない.もし,これ相当のことがしたい場合,以下のように <tt class="docutils literal">newtype</tt> を挟んでやる必要がある:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">ConstFunc</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">ConstFunc</span><span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">r</span><span class="p">)</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">ConstFunc</span><span class="w"> </span><span class="kt">Bool</span><span class="p">,</span><span class="w"> </span><span class="kt">ConstFunc</span><span class="w"> </span><span class="kt">Int</span><span class="p">)</span>
<span class="nf">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="kt">ConstFunc</span><span class="w"> </span><span class="p">(</span><span class="n">const</span><span class="w"> </span><span class="kt">True</span><span class="p">),</span><span class="w"> </span><span class="kt">ConstFunc</span><span class="w"> </span><span class="p">(</span><span class="n">const</span><span class="w"> </span><span class="mi">0</span><span class="p">))</span>
</pre></div></td></tr></table></div>
<p>一般に, <tt class="docutils literal">RankNTypes</tt> には「型のパラメータに,多相的な型を割り当てることはできない」という制約がある.上の例では,タプルのコンストラクタは, <tt class="docutils literal"><span class="pre">(,)::</span> forall a b. a <span class="pre">-></span> b <span class="pre">-></span> (a, b)</tt> という型を持つため,パラメータ <tt class="docutils literal">a</tt> に <tt class="docutils literal">forall a. a <span class="pre">-></span> Bool</tt> という多相の型を, <tt class="docutils literal">b</tt> にも <tt class="docutils literal">forall a. a <span class="pre">-></span> Int</tt> という多相の型を割り当てる必要が出てくる.これが <tt class="docutils literal">RankNTypes</tt> の制約に違反するのだ.<tt class="docutils literal">newtype</tt> で作った型の方は単相であり,多相的でないため,この制約を回避できるわけだ.</p>
<p>上記の制約は,可述的多相 (predicative polymorphism) という名前の体系として知られており,この制約さえ取っ払ってしまった体系を非可述的多相 (impredicative polymorphism) または第一級多相 (first-class polymorphism) と呼ぶ.可述的多相では上記のように,多相関数を要素に持つタプルなどは直接は作れないわけで,その意味で単相的な値より劣るわけだが,非可述的多相になるとそれすら取り扱えるようになる.そうなると多相関数を第一級で取り扱えると言って良いだろう.しかし,この体系は幾つか理論的・技術的な困難が知られている.興味があれば調べてみると良いだろう <a class="footnote-reference" href="#first-class-poly-infer" id="auto-id-11">[8]</a> .</p>
</div>
<div class="section" id="auto-id-12">
<h2>まとめ<a class="headerlink" href="#auto-id-12" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで <tt class="docutils literal">RankNTypes</tt> 拡張の紹介をした.見て回った感じ,案外 <tt class="docutils literal">RankNTypes</tt> の日本語文献がなかったのが書こうとした動機.なお,この記事中で,いくつか書かなきゃなみたいなこと結構省略したし,割と何も考えずに今持ってる知識だけで書いてるので,間違い結構あるかもしれん.その内,需要ありそうだったら,ちゃんと参考文献とか諸々付けたものをどっかに寄稿したいなとは思ってる.未来の俺,がんばってくれ.てことで,以上.</p>
<table class="docutils footnote" frame="void" id="existential-types" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[1]</a></td><td>なお,あるパラメータでその型が成り立つ型は存在型と呼ばれ, GHC 拡張で別に搭載されており, <tt class="docutils literal">ExistentialQuantification</tt> 拡張を使うことで実現できる.これは紛らわしいことに今回紹介する <tt class="docutils literal">RankNTypes</tt> と効果が似て非なるもので,しかも同じキーワードを使うため混同しがちだが,混同してはならない.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-inlining" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[2]</a></td><td>インライン展開により一部単相的に扱えることが分かった場合には,テンプレート方式による切り替えが行われる場合もある.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="using-type-class-for-polymorphic-representation" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[3]</a></td><td>というのは嘘で,実は Haskell 標準の範囲でも型クラスを使うことで多相関数表現をエンコードすることができる.具体的な例は後ほどの脚注で.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="implement-pshow-using-type-class" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[4]</a></td><td>先ほどの脚注で多相関数表現を型クラスでエンコードできるという話をしたが,今回は <tt class="docutils literal">class A p where pshow :: Show a => Proxy p <span class="pre">-></span> a <span class="pre">-></span> String</tt> みたいな型クラスを書き,型 <tt class="docutils literal">p</tt> を切り替えることで,実は実装を切り替えられる.その意味では実は何とかなったりするのだが,これはこれで色々不便なことがあるので,まあそういう感じ.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="notice-rankntypes-restriction" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[5]</a></td><td>というのは実は言い過ぎで, <tt class="docutils literal">RankNTypes</tt> 拡張下でも幾つか制限がある.それについては,最後の節で扱うのでそっちを参照してくれ.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="kan-extensions-for-optimization" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-9">[6]</a></td><td><a class="reference external" href="https://link.springer.com/chapter/10.1007/978-3-642-31113-0_16">https://link.springer.com/chapter/10.1007/978-3-642-31113-0_16</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="constraints-package" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-10">[7]</a></td><td><a class="reference external" href="https://hackage.haskell.org/package/constraints">https://hackage.haskell.org/package/constraints</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="first-class-poly-infer" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-11">[8]</a></td><td><a class="reference external" href="https://www.microsoft.com/en-us/research/publication/guarded-impredicative-polymorphism/">https://www.microsoft.com/en-us/research/publication/guarded-impredicative-polymorphism/</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/12/rankntypes-a-ghc-extension.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/12/rankntypes-a-ghc-extension.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>babel と core-js を使って,古いブラウザをサポートする2019-11-27T08:19:16+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-11-27:/blog/posts/2019/11/support-more-web-using-babel/<p>Sentry でたまに,古い OS からのアクセスによるエラーレポートが来る.現状,このブログの JS は <tt class="docutils literal">let</tt> / <tt class="docutils literal">const</tt> 普通に使ってるし, <tt class="docutils literal"><span class="pre">for-of</span></tt> な …</p><p>Sentry でたまに,古い OS からのアクセスによるエラーレポートが来る.現状,このブログの JS は <tt class="docutils literal">let</tt> / <tt class="docutils literal">const</tt> 普通に使ってるし, <tt class="docutils literal"><span class="pre">for-of</span></tt> なども使っている.なので,一世代前のブラウザなどを使っていると,そこら辺の機能に対応していなくてエラーになる.試しにこの辺を改善してみると,どうなるかのか観測してみたいなと思って,ちょっとサイト設定をいじってみた.そのメモ.</p>
<p>なお,使った環境は以下のもの:</p>
<table border="1" class="docutils">
<colgroup>
<col width="50%"/>
<col width="50%"/>
</colgroup>
<tbody valign="top">
<tr><td>babel</td>
<td>7.7.4</td>
</tr>
<tr><td>core-js</td>
<td>3.4.2</td>
</tr>
<tr><td>webpack</td>
<td>4.41.2</td>
</tr>
</tbody>
</table>
<div class="section" id="babel-polyfill">
<h2>Babel と PolyFill<a class="headerlink" href="#babel-polyfill" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Sentry でたまに,以下のようなエラーが報告されていた.</p>
<ul class="simple">
<li><tt class="docutils literal">SyntaxError: Unexpected end of input</tt></li>
<li><tt class="docutils literal">TypeError: <span class="pre">document.querySelectorAll(...)[Symbol.iterator]</span> is not a function</tt></li>
</ul>
<p>おそらくこれらは,ブログの JavaScript が割と新しい構文を使っているためと思われる.で, Web の移行の黎明期は,こういった状況に対応するため,新しい構文を使用したプログラムからそれらを除いたプログラムへのトランスパイラと,古いオブジェクトに新しい API を追加する polyfill が活躍していた.最近は,セキュリティ的な面とこうした状況に対応していくため,ブラウザの自動更新機能が増強され, OS においてもかなりのサポートが入っており,これらを採用しなくても個人レベルなら何とかなる場合が多い.というか,うちのブログは今まで何とかなっていた.</p>
<p>トランスパイラや polyfill は,そういった背景もあって無数にあるのだが,その中で首位を占めているのが babel だ. babel は主にトランスパイラを提供しているが,その周辺ツールもまとめて色々提供しており, <tt class="docutils literal">@babel/polyfill</tt> もその一つだ.ただ,現在は <tt class="docutils literal">@babel/polyfill</tt> は非推奨になっていて,中身は <tt class="docutils literal"><span class="pre">core-js</span></tt> と <tt class="docutils literal"><span class="pre">regenerator-runtime</span></tt> というパッケージを読むようになっており,直接これらのパッケージを使うことが推奨されている. <tt class="docutils literal"><span class="pre">core-js</span></tt> は様々な polyfill をまとめてモジュール単位で提供しており, <tt class="docutils literal"><span class="pre">regenerator-runtime</span></tt> は generator や async/await などの機能をサポートするための generator のエミュレータが入った軽量のパッケージになっている. babel で吐き出したコードを動かすための <tt class="docutils literal">@babel/runtime</tt> パッケージは,実際には幾つかの単純なヘルパ関数と <tt class="docutils literal"><span class="pre">regenerator-runtime</span></tt> を再エクスポートして提供しているだけだ.</p>
<p>実際に babel が書いた JavaScript をどうトランスパイルするのか見てみる.まず, babel の cli をインストールする:</p>
<pre class="literal-block">
npm i -D @babel/core @babel/cli @babel/preset-env
</pre>
<p><tt class="docutils literal">@babel/core</tt> が babel トランスパイラの本体. <tt class="docutils literal">@babel/cli</tt> が <tt class="docutils literal">@babel/core</tt> を使う CLI を提供してくれるパッケージになっている.あと, babel は吐き出す JavaScript でどんくらいのレベルの構文を使うか指定できて,デフォルトのいい感じにしてくれる出力を行う際使うパッケージが <tt class="docutils literal"><span class="pre">@babel/preset-env</span></tt> になっている.こいつらをインストールしたら,以下のような感じで試すことができる:</p>
<pre class="literal-block">
$ echo "function* gen() { yield 1; }; export const g = gen();" \
| npx babel --no-babelrc --presets @babel/preset-env
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.g = void 0;
var _marked =
/*#__PURE__*/
regeneratorRuntime.mark(gen);
function gen() {
return regeneratorRuntime.wrap(function gen$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return 1;
case 2:
case "end":
return _context.stop();
}
}
}, _marked);
}
;
var g = gen();
exports.g = g;
</pre>
<p>このコードは, <tt class="docutils literal">@babel/runtime</tt> を別途読み込むことを前提としているが, <tt class="docutils literal"><span class="pre">@babel/plugin-transform-runtime</span></tt> プラグインを使うことで,明示的にモジュール読み込みをさせることもできる:</p>
<pre class="literal-block">
$ npm i -D @babel/plugin-transform-runtime
$ echo "function* gen() { yield 1; }; export const g = gen();" \
| npx babel --no-babelrc --presets @babel/preset-env --plugins @babel/plugin-transform-runtime
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.g = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _marked =
/*#__PURE__*/
_regenerator["default"].mark(gen);
function gen() {
return _regenerator["default"].wrap(function gen$(_context) {
...
}, _marked);
}
...
</pre>
<p>こんな具合に generator や async/await は <tt class="docutils literal"><span class="pre">regenerator-runtime</span></tt> を使ったコードに変換されるし, let / const や arrow function はただの var や function に変換される.ただ,これだけでは旧世代のブラウザに対応できない可能性がある.例えば, <tt class="docutils literal">document.querySelectorAll</tt> が返す <tt class="docutils literal">NodeList</tt> という抽象インターフェースは,通常の <tt class="docutils literal">Array</tt> インスタンスと同様に扱えるように <tt class="docutils literal">forEach</tt> メソッドやイテレータが搭載されているが,これが搭載されたのは Chrome でバージョン 51 から, IE では搭載されていないというサポート状況になっている.そのため,これらのブラウザの上でサポートされている JavaScript の構文のみを使った場合でも,プログラム自体が意図通りに動かない可能性がある.実際, Sentry で報告されてきた <tt class="docutils literal">TypeError</tt> はそれが原因だと思われる.</p>
<p>これらの API レベルのフォールバックを提供する polyfill で, babel で推奨されているパッケージが <tt class="docutils literal"><span class="pre">core-js</span></tt> だ.例えば, <tt class="docutils literal">NodeList</tt> の <tt class="docutils literal">forEach</tt> メソッドの polyfill は, <tt class="docutils literal"><span class="pre">core-js</span></tt> パッケージの <tt class="docutils literal"><span class="pre">core-js/modules/web.dom-collections.for-each.js</span></tt> というモジュールで提供されている.なお,ソースコードが大きくなることを許容するなら,すべての polyfill をまとめたモジュールとして <tt class="docutils literal"><span class="pre">core-js</span></tt> モジュールを単にインポートするだけでよい:</p>
<pre class="literal-block">
import "core-js";
</pre>
<p>こうすることで,古い世代のクライアントでもある程度は動作が保証されることになる.</p>
</div>
<div class="section" id="babel-loader">
<h2>babel-loader を使う<a class="headerlink" href="#babel-loader" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,このブログでは現状 Webpack を使ってモジュールシステムを管理している. Webpack 上で babel を使用したいなら, <tt class="docutils literal"><span class="pre">babel-loader</span></tt> パッケージを使えばよい.具体的には,まず以下のパッケージを依存に追加する:</p>
<pre class="literal-block">
npm i -S @babel/runtime
npm i -D @babel/core babel-loader @babel/preset-env @babel/plugin-transform-runtime
</pre>
<p>後は,以下の設定を <tt class="docutils literal">webpack.config.js</tt> に追加する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span><span class="w"> </span> module: {
<span class="w"> </span> rules: [
<span class="w"> </span> {
<span class="gi">+ test: /\.m?js$/,</span>
<span class="gi">+ exclude: /(node_modules|bower_components)/,</span>
<span class="gi">+ use: {</span>
<span class="gi">+ loader: 'babel-loader',</span>
<span class="gi">+ options: {</span>
<span class="gi">+ presets: ['@babel/preset-env'],</span>
<span class="gi">+ plugins: ['@babel/plugin-transform-runtime']</span>
<span class="gi">+ }</span>
<span class="gi">+ }</span>
<span class="gi">+ },</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">.mjs</tt> は Node.js などでサポートされている拡張子で, ES6 のモジュールシステムを使うプログラムに慣例として用いられているもの.うちではその拡張子を使ってないけど,とりあえず慣例として追加しておく.このようにしておけば,新しい構文は babel がいい感じにトランスパイルしてくれ,モジュールシステムは webpack がいい感じに解決してパッキングしてくれるようになる.後は, entrypoint のプログラムで <tt class="docutils literal"><span class="pre">core-js</span></tt> を読み込み用にしておけばよいだろう.</p>
</div>
<div class="section" id="auto-id-1">
<h2>まとめ<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>とりあえず, Sentry のノイズ消しとお試しのためフォールバックするようにしてみた.これで,どんな感じになるかしばらく様子見てみようと思う.</p>
<p>うちのブログは JavaScript 切っても見れるよう,致命的なところに JavaScript 使っていないはずなので,特にアクセス状況に影響があるわけじゃないと思う.それに最近だとほとんどのブラウザは自動的に最新に保たれる (と信じてる) だろうし, JavaScript が動かない環境はほんの一握りな気がする.ただ,ブログを自分でコード管理しながら運営すると,こういう感じで色々アクセスに対して実験できていいなという感じなので,そういう実験はいろいろしていきたい.そういう感じで.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/11/support-more-web-using-babel.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/11/support-more-web-using-babel.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>type family を使って再帰的 ADT をオープンにする2019-11-17T06:42:24+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-11-17:/blog/posts/2019/11/trees-that-grow/<p>元ネタは <a class="reference external" href="https://www.microsoft.com/en-us/research/publication/trees-that-grow/">Trees that grow</a> . Haskell では代数的データ型 (ADT) を使ってプログミングに使うデータ構造を定義し,その構造を操作するこ …</p><p>元ネタは <a class="reference external" href="https://www.microsoft.com/en-us/research/publication/trees-that-grow/">Trees that grow</a> . Haskell では代数的データ型 (ADT) を使ってプログミングに使うデータ構造を定義し,その構造を操作することによりプログラミングを行う. ADT はパターンマッチが容易で,再帰的に定義でき,基本的に閉じた構造になっている.そのため便利な反面,その機能が保守で仇となる場合もある.この問題は古くから知られており,いくつかの解決策も提案されてきた.今回はこのうち,現在 GHC で採用されつつある type family を使った解決方法を紹介する.</p>
<p>なお,環境として以下を想定している.</p>
<table border="1" class="docutils">
<colgroup>
<col width="69%"/>
<col width="31%"/>
</colgroup>
<tbody valign="top">
<tr><td>GHC のバージョン</td>
<td>8.8.1</td>
</tr>
</tbody>
</table>
<div class="section" id="the-expression-problem">
<h2>The Expression Problem<a class="headerlink" href="#the-expression-problem" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>プログラミング,特に Haskell を使用したプログラミングにおいて,データ型は非常に重要な役割を持つ.特に,一部のプログラムにおいては,根幹をなすデータ型がいくつか存在するような場合もある.この場合データ型の扱いをどうするかは設計段階において非常に重要になる.例えば,コンパイラを作る場合を想定すると,多くの場合 AST の定義とコンテキストの定義が非常に重要になるだろう.この場合に, AST に話を絞ると,プログラムのフェーズによって AST に対し少し情報を足したりしたい場合がある.この場合データ型自体は異なるが,ほぼ基盤は変わらない.このため,それぞれデータ型を定義するとなると,共通の処理関数やインターフェースなども再定義する必要に迫られ,ボイラープレートが大量に生まれることになる.また,元々あった構文を脱糖し,その後はその構文がない前提で話を進めたい場合などもあるだろう.この場合も,脱糖後用に新たにデータ型を定義し直すのは手間である.</p>
<p>一般に上のように,場合分け可能なデータ型に対し,既存の処理関数やデータ型を再定義することなく,新たな場合分けを追加できるかという問題は Expression Problem と名付けられている <a class="footnote-reference" href="#the-expression-problem-detail" id="auto-id-1">[1]</a> .特に純粋な ADT しか持たないような Haskell などの言語は Expression Problem に弱く, Scala などのオブジェクト指向を採用してる言語はこのような問題にはかなり強い.例えば,足算を行う電卓の例を考えてみる. AST の定義とそれに対しての実行関数だけ書いてみると,それぞれ以下のようになるだろう:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">-- Haskell</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Ast</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Add</span><span class="w"> </span><span class="kt">Ast</span><span class="w"> </span><span class="kt">Ast</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Num</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">eval</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">AST</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">eval</span><span class="w"> </span><span class="p">(</span><span class="kt">Add</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">eval</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">eval</span><span class="w"> </span><span class="n">y</span>
<span class="nf">eval</span><span class="w"> </span><span class="p">(</span><span class="kt">Num</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">i</span>
</pre></div></td></tr></table></div>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">// Scala</span>
<span class="k">trait</span><span class="w"> </span><span class="nc">Ast</span>
<span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Add</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">Ast</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="nc">Ast</span><span class="p">)</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">Ast</span>
<span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Num</span><span class="p">(</span><span class="n">i</span><span class="p">:</span><span class="w"> </span><span class="nc">Int</span><span class="p">)</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">Ast</span>
<span class="k">def</span><span class="w"> </span><span class="nf">eval</span><span class="p">(</span><span class="n">t</span><span class="p">:</span><span class="w"> </span><span class="nc">Ast</span><span class="p">):</span><span class="w"> </span><span class="nc">Int</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">Add</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">eval</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">eval</span><span class="p">(</span><span class="n">y</span><span class="p">)</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">Num</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">i</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>これらのプログラムで遊び終えたら,多くの人はこの電卓に新たな機能を足したいと思うはずだ.例えば,掛け算を追加してみることを考えたい.上のプログラムを全く変えないで,行末に何かを追加するだけで,掛け算も計算できるようにならないだろうか? 残念ながら今回の場合は,不可能だ.しかし, Scala の場合少し工夫するだけでこの目標を達成できる.最初のプログラムを以下のように作っておくのだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">// Scala</span>
<span class="k">trait</span><span class="w"> </span><span class="nc">Ast</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">eval</span><span class="p">():</span><span class="w"> </span><span class="nc">Int</span>
<span class="p">}</span>
<span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Add</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">Ast</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="nc">Ast</span><span class="p">)</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">Ast</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">eval</span><span class="p">():</span><span class="w"> </span><span class="nc">Int</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="n">eval</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">.</span><span class="n">eval</span><span class="p">()</span>
<span class="p">}</span>
<span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Num</span><span class="p">(</span><span class="n">i</span><span class="p">:</span><span class="w"> </span><span class="nc">Int</span><span class="p">)</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">Ast</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">eval</span><span class="p">():</span><span class="w"> </span><span class="nc">Int</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>この場合,掛け算を追加したかったら,行末に以下を追記すれば良い:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Mul</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">Ast</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">:</span><span class="w"> </span><span class="nc">Ast</span><span class="p">)</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">Ast</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">eval</span><span class="p">():</span><span class="w"> </span><span class="nc">Int</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="n">eval</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">y</span><span class="p">.</span><span class="n">eval</span><span class="p">()</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>残念ながら, Haskell では同じことをやろうとすると,大規模な改築が必要になる.原因はデータ型が再帰的であることによる. <tt class="docutils literal">Ast</tt> は再帰的であるため,単純に以下のようなことをしても掛け算を追加したことにはならない:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Ast2</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Orig</span><span class="w"> </span><span class="kt">Ast</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Mul</span><span class="w"> </span><span class="kt">Ast2</span><span class="w"> </span><span class="kt">Ast2</span>
</pre></div></td></tr></table></div>
<p>なぜなら, <tt class="docutils literal">(2 * 3) + 1</tt> のようなものをこのデータ型では表現できないからだ.つまり,元々の再帰構造自体はデータ型を定義した時点で既に確定してしまっており,後から付け入る隙がないのだ.逆に Scala では再帰部分をベースのトレイトで定義しており,後から派生クラスをいくらでも追加することができる.一般にオブジェクト指向型の言語では,再帰部分をオブジェクトの基底インターフェースにすることで,自然なプログラミングスタイルながら後から再帰部分をいくらでも派生させることができる.このような特性は,開いた再帰 (open recursion) と呼ばれる.これは,オブジェクト指向を搭載する言語の大きな強みだと個人的には思っている <a class="footnote-reference" href="#open-vs-close" id="auto-id-2">[2]</a> .</p>
<p>Haskell では,この問題の解決が結構昔から取り組まれており, tagless final <a class="footnote-reference" href="#finally-tagless-ref" id="auto-id-3">[3]</a> , data types a la carte <a class="footnote-reference" href="#data-types-a-la-carte-ref" id="auto-id-4">[4]</a> などの手法が存在する.今回は,これらの提案の手法のうち,比較的新しく GHC で使われている, type family を使った手法について紹介する.</p>
</div>
<div class="section" id="auto-id-5">
<h2>Trees That Grow<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>この手法の面白いところは,他の手法と比べ,かなり自然な Haskell プログラミングの形でデータ型を拡張できることにある.つまりかなり単純な手法で,拡張性を持つデータ型を扱え,オープン性を type family のオープン性を使って担保するだけだ.</p>
<p>type family とは, GHC の言語拡張で提供される機能で,その名の通り型の族,つまりある型に対して別の型を結びつけるような写像を定義できる機能だ.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE TypeFamilies #-}</span>
<span class="cm">{-# LANGUAGE PolyKinds #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Data.Kind</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">family</span><span class="w"> </span><span class="kt">ElemType</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Type</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Type</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">ElemType</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">a</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">ElemType</span><span class="w"> </span><span class="p">(</span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">a</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">ElemType</span><span class="w"> </span><span class="kt">Text</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Char</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">ElemType</span><span class="w"> </span><span class="kt">ByteString</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Word8</span>
</pre></div></td></tr></table></div>
<p>のように書くと, <tt class="docutils literal">ElemType String</tt> や <tt class="docutils literal">ElemType Text</tt> が <tt class="docutils literal">Char</tt> 型のエイリアスとして使えるようになる.型でパターンマッチできる,型エイリアスだと思っても良いだろう.ただ,この機能の面白いところは,パターンマッチを後からいくらでも足せるところにある <a class="footnote-reference" href="#closed-type-families" id="auto-id-6">[5]</a> .この機能を使うと,上の電卓の例を次のように修正することができる.</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE ScopedTypeVariables #-}</span>
<span class="cm">{-# LANGUAGE TypeApplications #-}</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Add</span><span class="w"> </span><span class="p">(</span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Num</span><span class="w"> </span><span class="kt">Integer</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">XAst</span><span class="w"> </span><span class="p">(</span><span class="kt">XAst</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">family</span><span class="w"> </span><span class="kt">XAst</span><span class="w"> </span><span class="p">(</span><span class="n">p</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Type</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Type</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">EvalXAst</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">evalXAst</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Integer</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">XAst</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Integer</span>
<span class="nf">eval</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">p</span><span class="o">.</span><span class="w"> </span><span class="kt">EvalXAst</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Integer</span>
<span class="nf">eval</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">goXAst</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">evalXAst</span><span class="w"> </span><span class="o">@</span><span class="n">p</span><span class="w"> </span><span class="n">go</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">Add</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">y</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">Num</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">i</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">XAst</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">goXAst</span><span class="w"> </span><span class="n">x</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">OldAst</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XAst</span><span class="w"> </span><span class="kt">OldAst</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Void</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">EvalXAst</span><span class="w"> </span><span class="kt">OldAst</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">evalXAst</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">absurd</span><span class="w"> </span><span class="n">x</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">WithMul</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Mul</span><span class="w"> </span><span class="p">(</span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">NewAst</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XAst</span><span class="w"> </span><span class="kt">NewAst</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">WithMul</span><span class="w"> </span><span class="kt">NewAst</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">EvalXAst</span><span class="w"> </span><span class="kt">NewAst</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">evalXAst</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">Mul</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">y</span>
</pre></div></td></tr></table></div>
<p>ちょっと複雑に見えるのが,基幹部は <tt class="docutils literal">Ast p</tt> の <tt class="docutils literal">XAst</tt> というデータコンストラクタだ. <tt class="docutils literal">XAst</tt> データコンストラクタは type family で定義されたデータ型を受け取るようになっており, type family のインスタンスを後から挿入できるようになっている. <tt class="docutils literal">EvalXAst</tt> は後から挿入するコンストラクタの,パターンマッチ部分を受けとるようになっていて, <tt class="docutils literal">eval</tt> はそいつを受け取って完成するようになっている.その下が実際のパターンマッチを後付けしてる部分で, <tt class="docutils literal">Ast OldAst</tt> は元々の足し算しかない電卓の動作, <tt class="docutils literal">Ast NewAst</tt> は掛け算も追加した電卓の動作が行えるようになっている.このように, type family をデータ型に埋め込むことで,データ型を一部オープンにすることができるようになる.さらに,この手法は上の Scala の例と異なり,様々なバリエーションのデータ型を双方共存させることができる.</p>
<p>この手法は, Expression Problem 以外にも応用できる.最初にあげた,フェーズごとに異なる情報を入れるようなデータ型にも対応できる.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Type</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">NumType</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">ArrowType</span><span class="w"> </span><span class="kt">Type</span><span class="w"> </span><span class="kt">Type</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">App</span><span class="w"> </span><span class="p">(</span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Abs</span><span class="w"> </span><span class="kt">String</span><span class="w"> </span><span class="p">(</span><span class="kt">Ast</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Var</span><span class="w"> </span><span class="p">(</span><span class="kt">XVar</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="kt">String</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Num</span><span class="w"> </span><span class="kt">Integer</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">family</span><span class="w"> </span><span class="kt">XVar</span><span class="w"> </span><span class="n">p</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Parsed</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XVar</span><span class="w"> </span><span class="kt">Parsed</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">NoExt</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Renamed</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XVar</span><span class="w"> </span><span class="kt">Renamed</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">String</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">TypeChecked</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XVar</span><span class="w"> </span><span class="kt">TypeChecked</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="kt">XVar</span><span class="w"> </span><span class="kt">Renamed</span><span class="p">,</span><span class="w"> </span><span class="kt">Type</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>みたいなデータ型を作ると,パース時は何の情報もないのが,リネーム時に元々の変数名を,型検査時に変数の型を, AST のデータ型に付与することができる.</p>
<p>さらに, type family のインスタンスはモジュールを超えて定義できるため,インポートするモジュールを変更することでデータ型に付加する拡張を変更することもできる.かなり応用が効くだろう.</p>
</div>
<div class="section" id="ghc">
<h2>GHC での利用<a class="headerlink" href="#ghc" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>GHC での移行計画は, <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/wikis/implementing-trees-that-grow">GHC Wiki</a> に記載されている.ゴールとして,</p>
<ul class="simple">
<li>GHC で使っている AST</li>
<li>Template Haskell で使っている AST</li>
<li><tt class="docutils literal"><span class="pre">haskell-src-exts</span></tt> で使っている AST</li>
</ul>
<p>を共通化するという壮大な計画のようだ.現在は, trees that grow 用の type family は, <a class="reference external" href="https://downloads.haskell.org/~ghc/latest/docs/html/libraries/ghc-8.8.1/HsExtension.html">HsExtension</a> モジュールに纏まっている.そして,内部の AST に関するデータ型は,次のようになっている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">HsExpr</span><span class="w"> </span><span class="n">p</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">HsVar</span><span class="w"> </span><span class="p">(</span><span class="kt">XVar</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Located</span><span class="w"> </span><span class="p">(</span><span class="kt">IdP</span><span class="w"> </span><span class="n">p</span><span class="p">))</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">XExpr</span><span class="w"> </span><span class="p">(</span><span class="kt">XXExpr</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XVar</span><span class="w"> </span><span class="p">(</span><span class="kt">GhcPass</span><span class="w"> </span><span class="kr">_</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">NoExt</span>
<span class="o">...</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XXExpr</span><span class="w"> </span><span class="p">(</span><span class="kt">GhcPass</span><span class="w"> </span><span class="kr">_</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">NoExt</span>
</pre></div></td></tr></table></div>
<p>それぞれの基幹となるデータ型は,次のようになっている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE DataKinds #-}</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">NoExt</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">NoExt</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">GhcPass</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Pass</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">Pass</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Parsed</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Renamed</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Typechecked</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">GhcPs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GhcPass</span><span class="w"> </span><span class="kt">'Parsed</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">GhcRn</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GhcPass</span><span class="w"> </span><span class="kt">'Renamed</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">GhcTc</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GhcPass</span><span class="w"> </span><span class="kt">'Typechecked</span>
</pre></div></td></tr></table></div>
<p>例えば,演算子適用を表すコンストラクタは,次のようになっている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">type</span><span class="w"> </span><span class="kt">LHsExpr</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Located</span><span class="w"> </span><span class="p">(</span><span class="kt">HsExpr</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">HsExpr</span><span class="w"> </span><span class="n">p</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">OpApp</span><span class="w"> </span><span class="p">(</span><span class="kt">XOpApp</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">LHsExpr</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">LHsExpr</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">LHsExpr</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">...</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XOpApp</span><span class="w"> </span><span class="kt">GhcPs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">NoExt</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XOpApp</span><span class="w"> </span><span class="kt">GhcRn</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Fixity</span>
<span class="kr">type</span><span class="w"> </span><span class="kr">instance</span><span class="w"> </span><span class="kt">XOpApp</span><span class="w"> </span><span class="kt">GhcTc</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Fixity</span>
</pre></div></td></tr></table></div>
<p>演算子適用は,パース時は全て優先順位同じで左結合として扱われ,リネーム時に結合や優先順位が解決される.その解決された情報が,リネーム時から入ってるというわけだ.で,拡張部分については随時制約が用意されていて,例えば <tt class="docutils literal">HsExpr</tt> 用には,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">type</span><span class="w"> </span><span class="kt">ForallXExpr</span><span class="w"> </span><span class="p">(</span><span class="n">c</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Constraint</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span>
<span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="p">(</span><span class="kt">XVar</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="p">(</span><span class="kt">XXExpr</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>みたいなエイリアスが <a class="reference external" href="https://downloads.haskell.org/~ghc/latest/docs/html/libraries/ghc-8.8.1/HsExtension.html">HsExtension</a> モジュールにあったりする.クラスインスタンスを作りたいときは,このエイリアスを使って作っていくという感じになるだろう.その書き換えとともにパーサやリネーム部分のリファクタリング計画もあるようで,今現在遂行中という感じっぽい.とりあえず, GHC で <tt class="docutils literal">X</tt> と付くデータ型が出てきたら, tree that grows のものと思っていいと思う.内部的にはそこまで本格的な対応は入っていなくて, <tt class="docutils literal">XExpr</tt> コンストラクタなどは来ない前提で来たら <tt class="docutils literal">panic</tt> にするという処理になっているっぽいけど.</p>
</div>
<div class="section" id="auto-id-7">
<h2>まとめ<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで,今回は type family による拡張性を持ったデータ型の定義方法について紹介した.この手法は結構示唆に富んでいると思う. Haskell では通常その定義内で閉じたデータ型しか作れない訳だけど, type family を使うことで定義を外から容易に拡張できるようにできる訳だ.つまり,オープン性を type family により調整できる訳だ.最もオブジェクト指向では,多くの場合もっと細かく権限が制御できたりする訳だけど,残念ながら type family だとそこまで細かく制御はできない.細かい制御がそこまでいるかというのは議論の余地があるかもしれないけど,そこらへんも現在の機能でなんとかできるか考えてみると面白いかもなと思ったりした.</p>
<p>とりあえず, GHC で本格的に用いられるようになってきた機能なので, GHC のコードを読む時用と Haskell プログラミングの技術の一つとしてまとめておいた.実はそこまで真面目に元論文を読んでないので,機会があればもうちょっと真面目に元論文読んでおきたい.今回は以上.</p>
<table class="docutils footnote" frame="void" id="the-expression-problem-detail" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td>名付け親は Wadler 先生で,大学のプログラミング言語開発チームの ML で初めて使ったとされている.ML に投稿されたメールは, <a class="reference external" href="http://homepages.inf.ed.ac.uk/wadler/papers/expression/expression.txt">http://homepages.inf.ed.ac.uk/wadler/papers/expression/expression.txt</a> で公開されている.なお,厳密にはここでの定義は元々の定義と違っていて,元々の定義は「元々あるコードの再コンパイルやキャストなどの型変換操作を必要とせずに,新たな場合分けを追加できるか」というもの.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="open-vs-close" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td>デフォルトで open か close かは,それぞれ一長一短でもあり, open は拡張性がある反面,第三者が契約外の拡張を加えてしまう可能性があり,それらを保守の際きちんと管理する責任が生まれる.逆に close の場合そのような管理責任は生まれないが,拡張性のなさをボイラープレートなど冗長な作業により埋めなければならない.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="finally-tagless-ref" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[3]</a></td><td><a class="reference external" href="http://okmij.org/ftp/tagless-final/index.html">http://okmij.org/ftp/tagless-final/index.html</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="data-types-a-la-carte-ref" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[4]</a></td><td><a class="reference external" href="https://dl.acm.org/citation.cfm?id=1394795">https://dl.acm.org/citation.cfm?id=1394795</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="closed-type-families" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[5]</a></td><td>なお,パターンマッチを後から足せないようにする機能も用意されており, <tt class="docutils literal">type family</tt> 宣言の際 <tt class="docutils literal">where</tt> を書くと,その後に書いたインスタンス以外はインスタンスを登録できないようになる.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/11/trees-that-grow.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/11/trees-that-grow.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>pipenv を WSL/Debian で使う際の注意事項2019-11-14T08:59:47+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-11-14:/blog/posts/2019/11/pipenv-on-wsl-debian/<p>久しぶりに Windows 上で環境構築をすることになったんだけど,その際 Pipenv をインストールするのにちょっと躓いたので,そ …</p><p>久しぶりに Windows 上で環境構築をすることになったんだけど,その際 Pipenv をインストールするのにちょっと躓いたので,その備忘録.</p>
<div class="section" id="pipenv">
<h2>Pipenv を入れた時のエラー<a class="headerlink" href="#pipenv" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Windows 上で開発する際は, WSL/Debian を使っている.で,新しい環境でもこれで行くことにして, Pipenv を Python3 環境で使いたかったので,次のようにして入れた:</p>
<pre class="literal-block">
sudo apt update
sudo apt install -y python3-pip
pip3 install pipenv
</pre>
<p>これで,問題なく入ったように見えたんだけど,実際に実行してみると以下のような例外を吐いていた:</p>
<pre class="literal-block">
$ pipenv install
['Traceback (most recent call last):\n', ...]
Traceback (most recent call last):
...
File "/usr/lib/python3.7/subprocess.py", line 1522, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 8] Exec format error: '/mnt/c/.../AppData/Local/Microsoft/WindowsApps/python.exe'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
...
File "~/.local/lib/python3.7/site-packages/pipenv/vendor/vistir/misc.py", line 162, in _create_subprocess
sys.stderr.write("Error %s while executing command %s", exc, " ".join(cmd._parts))
TypeError: write() takes exactly one argument (3 given)
</pre>
<p>原因は詳しく調べてないけど,エラーメッセージからおそらく, Python3 のインタプリタを使わずに Python2 のを探してるんじゃないかと思ってる. Debian は現在 Python2 から Python3 の移行期で,デフォルトでは <tt class="docutils literal">python</tt> は Python2 のインタプリタ, <tt class="docutils literal">python3</tt> が Python3 のインタプリタというようになっている.で, <tt class="docutils literal">pipenv</tt> は Python3 の Pip で入れたにもかかわらず,内部で <tt class="docutils literal">python</tt> という名前でインタプリタを探してたりするんじゃないかなと考えている <a class="footnote-reference" href="#notice-details-for-this-issue" id="auto-id-1">[1]</a> .</p>
</div>
<div class="section" id="auto-id-2">
<h2>解決策<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>で,じゃあなんか解決する方法があるのかだけど,単純には次を実行すればいいっぽい:</p>
<pre class="literal-block">
pip3 uninstall -y pipenv
sudo apt install -y pipenv
</pre>
<p>または,問題が起きてるのが <tt class="docutils literal">virtualenv</tt> の環境を作る際に選択する Python のバージョンを間違えてることに起因してるっぽいので,一回環境を作ってその環境を使い続ける分には <tt class="docutils literal">pip3</tt> で入れたものでも大丈夫みたい. Debian のパッケージもあまり詳しく見てないけど, <tt class="docutils literal">pipenv</tt> パッケージはその辺うまいことするパッチでも当ててるってことかな? とりあえず,これで問題なく動いてるので,まいっかってなってる.</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>また詰まるかもしれないので,忘れる前にとりあえず書いといた.気が向けば原因調査したりするかも.後,今回は WSL で問題が起きたけど,普通に Debian 環境だと起きる問題だったりするかも.こちらからは以上です.</p>
<table class="docutils footnote" frame="void" id="notice-details-for-this-issue" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td>なんか原因知ってる人いたら教えてほしい.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/11/pipenv-on-wsl-debian.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/11/pipenv-on-wsl-debian.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>リテラルをコンパイラ時にチェックする2019-10-28T08:54:10+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-10-28:/blog/posts/2019/10/lint-bslit-by-ghc-plugin/<p>Haskell はいくつかのリテラルで型クラスを使用したオーバーロードを許容している.例えば,Haskell で <tt class="docutils literal">1</tt> と書いた場合,この型 …</p><p>Haskell はいくつかのリテラルで型クラスを使用したオーバーロードを許容している.例えば,Haskell で <tt class="docutils literal">1</tt> と書いた場合,この型は <tt class="docutils literal">1 :: Num a => a</tt> になり, <tt class="docutils literal">Num</tt> のインスタンスを定義することで,リテラルに対する実体をユーザも制御できるようになっている.GHC拡張で文字列に対してのオーバーロードなども提供されている.ただ,提供するデータ型とリテラルによっては,プログラムが意図通りに動かなかったりクラッシュしてしまったりすることがある.これを事前にチェックする仕組みを,コンパイラプラグインで実装する方法を紹介する.</p>
<p>なお,環境として以下を想定している.</p>
<table border="1" class="docutils">
<colgroup>
<col width="69%"/>
<col width="31%"/>
</colgroup>
<tbody valign="top">
<tr><td>GHC のバージョン</td>
<td>8.8.1</td>
</tr>
<tr><td>Cabal のバージョン</td>
<td>3.0.0.0</td>
</tr>
</tbody>
</table>
<div class="section" id="haskell">
<h2>Haskell のオーバーロードリテラル<a class="headerlink" href="#haskell" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Haskell では整数及び浮動小数点数リテラルにおいて,オーバーロードが許容されている.それぞれ,</p>
<ul class="simple">
<li>整数リテラル: <tt class="docutils literal">Num</tt> のインスタンス</li>
<li>浮動小数点数リテラル: <tt class="docutils literal">Fractional</tt> のインスタンス</li>
</ul>
<p>でオーバーロードされる.さらに, GHC 拡張で</p>
<ul class="simple">
<li><tt class="docutils literal">OverloadedStrings</tt>: 文字列リテラルを <tt class="docutils literal">IsString</tt> のインスタンスでオーバーロードする</li>
</ul>
<p>基本的に,この実装は何か基盤となるデータ型に対し,そこからキャストするようになっている.例えば,整数リテラル <tt class="docutils literal">1</tt> は <tt class="docutils literal">fromInteger (1 :: Integer)</tt> に変換されている.リテラルそれぞれで変換の仕方を挙げると,</p>
<ul class="simple">
<li>整数リテラル: <tt class="docutils literal">Integer</tt> から <tt class="docutils literal">fromInteger</tt> メソッドを使って変換</li>
<li>浮動小数点数リテラル: <tt class="docutils literal">Rational</tt> から <tt class="docutils literal">fromRational</tt> メソッドを使って変換</li>
<li>文字列リテラル: <tt class="docutils literal">String</tt> から <tt class="docutils literal">fromString</tt> メソッドを使って変換</li>
</ul>
<p>のようになる.ただ,このキャストは必ずしも安全とは限らない.例えば, <tt class="docutils literal">300 :: Data.Int.Int8</tt> というリテラルを考えると, <tt class="docutils literal">300</tt> は 符号付き8bit 表現の域を超えてしまっている.実際に GHCi 上で試してみると,以下の出力が得られる:</p>
<pre class="literal-block">
>>> 300 :: Data.Int.Int8
<interactive>:1:1: warning: [-Woverflowed-literals]
Literal 300 is out of the GHC.Int.Int8 range -128..127
44
</pre>
<p>このような意図しない挙動を防ぐため,GHC では標準で提供するデータ型のリテラルに対しては上のようなオーバーフローチェックをしてくれる.ただ,標準で提供されてないデータ型については,このようなチェックは行われない.有名な例が <tt class="docutils literal">ByteString</tt> に対する文字列リテラルのチェックだ. <tt class="docutils literal">ByteString</tt> は利便性のため <tt class="docutils literal">IsString</tt> のインスタンスを提供している.<tt class="docutils literal">ByteString</tt> は 8bit 文字の列で,バイト列の管理に使われる.ただ <tt class="docutils literal">String</tt> は Unicode 文字の列で, <tt class="docutils literal">ByteString</tt> は直接対応しない.そのため <tt class="docutils literal">IsString</tt> インスタンスの実装は,特定のエンコードを決めてバイト列に変換するか,全ての文字が 8bit 内に収まっていると仮定しての変換の二通りということになる.<tt class="docutils literal">ByteString</tt> では後者が選ばれている.そのため,以下のようなことが起こる:</p>
<pre class="literal-block">
>>> "あ" :: Data.ByteString.ByteString
"B"
</pre>
<p>このような予期しない動作をするリテラルを,コンパイル時に判定して警告を出したいことは良くあるので,それを実装してみる.</p>
</div>
<div class="section" id="ghc-compiler-plugin">
<h2>GHC Compiler Plugin<a class="headerlink" href="#ghc-compiler-plugin" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>GHC にはコンパイルフェーズを挟み込めるプラグインシステムが存在する.型検査や Core-to-Core の変換が主だったが, 8.6 からは Source Plugin と呼ばれる構文解析や型検査後に環境を弄れるプラグインが作れるようになった.今回はこのうち,型検査後にフェーズを挟み込める機能を使用し,リテラルに対しての警告を表示する.</p>
<p>プラグインの作り方のドキュメントは, <a class="reference external" href="https://downloads.haskell.org/~ghc/8.8.1/docs/html/users_guide/extending_ghc.html#compiler-plugins">GHCユーザガイド</a> を参照すると良いだろう.また, mpickering 先生による <a class="reference external" href="https://mpickering.github.io/plugins.html">まとめサイト</a> も参考になると思う.基本的には, <tt class="docutils literal">ghc</tt> パッケージの <a class="reference external" href="http://hackage.haskell.org/package/ghc-8.6.5/docs/Plugins.html#t:Plugin">GhcPlugins.Plugin</a> 型のデータを <tt class="docutils literal">plugin</tt> という名前でエクスポートしたモジュールを作り,そのモジュールを <tt class="docutils literal"><span class="pre">-fplugin=<module></span></tt> で指定してコンパイルを行えば良い.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">module</span><span class="w"> </span><span class="nn">PluginExample</span><span class="w"> </span><span class="kr">where</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">GhcPlugins</span>
<span class="nf">plugin</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">Plugin</span>
<span class="nf">plugin</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">defaultPlugin</span>
</pre></div></td></tr></table></div>
<p>のようなモジュールを作り, <tt class="docutils literal"><span class="pre">-fplugin=PluginExample</span></tt> をオプションに加えてコンパイルすれば良い.型検査後にフェーズを挟み込む場合,次のように書く:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">module</span><span class="w"> </span><span class="nn">PluginExample</span><span class="w"> </span><span class="kr">where</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">GhcPlugins</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">TcRnTypes</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">TcM</span>
<span class="nf">plugin</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">Plugin</span>
<span class="nf">plugin</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">defaultPlugin</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">typeCheckResultAction</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pluginAction</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">pluginAction</span>
<span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">CommandLineOption</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">ModSummary</span>
<span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcGblEnv</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcGblEnv</span>
<span class="nf">pluginAction</span><span class="w"> </span><span class="n">args</span><span class="w"> </span><span class="n">mods</span><span class="w"> </span><span class="n">tcEnv</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">doSomething</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">doSomething</tt> の部分はデフォルトでは <tt class="docutils literal">pure tcEnv</tt> で定義されている.それぞれの引数の内容は,</p>
<dl class="docutils">
<dt><tt class="docutils literal">args :: [CommandLineOption]</tt></dt>
<dd>プラグインのコマンドライン引数. <tt class="docutils literal"><span class="pre">-fplugin</span></tt> オプションで渡せるようになっている.</dd>
<dt><tt class="docutils literal">mods :: ModSummary</tt></dt>
<dd>対象モジュールの概要</dd>
<dt><tt class="docutils literal">tcEnv :: TcM.TcGblEnv</tt></dt>
<dd>型情報の解析に必要なものがいろいろ入っている.</dd>
</dl>
<p>みたいな感じ.後,プラグインは再コンパイルの必要性などを指定できて,デフォルトでは強制的に再コンパイルされるようになっている.特に <tt class="docutils literal">IO</tt> 処理に依存しないプラグインを書く場合は,次のようにしておくと良い:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">module</span><span class="w"> </span><span class="nn">PluginExample</span><span class="w"> </span><span class="kr">where</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">GhcPlugins</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">TcRnTypes</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">TcM</span>
<span class="nf">plugin</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">Plugin</span>
<span class="nf">plugin</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">defaultPlugin</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">pluginRecompile</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">purePlugin</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">typeCheckResultAction</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pluginAction</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p>デフォルトでは <tt class="docutils literal">GhcPlugins.impurePlugin</tt> が指定されている.フラグが変化した際に再コンパイルする <tt class="docutils literal">GhcPlugins.flagRecompile</tt> なども用意されている.</p>
</div>
<div class="section" id="ast">
<h2>AST を再帰的に探索する<a class="headerlink" href="#ast" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>では早速プラグインを作っていく.<tt class="docutils literal">TcGblEnv</tt> の <tt class="docutils literal">tcg_binds</tt> フィールドには,トップレベルの束縛の型検査済の AST が入っている.まず,この AST を再帰的に辿ってリテラル部分を見つけていく.再帰的に式を辿る関数を書いてもいいが,今回は <a class="reference external" href="http://hackage.haskell.org/package/syb">SYB (Scrap Your Boilerplate)</a> を使う.こいつは, <a class="reference external" href="http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Data.html#t:Data">Data</a> のインスタンスであれば,再帰関数を動的な型キャストなどを使ってうまく実装し,提供してくれるパッケージだ.こいつを使って,以下のようにすると,簡単にリテラル部分を全探索するコードを書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Generics.SYB</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">SYB</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">HsExtension</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">HsSyn</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">HsBinds</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">HsSyn</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">HsExpr</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">HsSyn</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">HsLit</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">HsSyn</span>
<span class="nf">pluginAction</span>
<span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">[</span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">CommandLineOption</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">ModSummary</span>
<span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcGblEnv</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcGblEnv</span>
<span class="nf">pluginAction</span><span class="w"> </span><span class="n">_args</span><span class="w"> </span><span class="n">_mods</span><span class="w"> </span><span class="n">tcEnv</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">lbinds</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="n">tcg_binds</span><span class="w"> </span><span class="n">tcEnv</span>
<span class="w"> </span><span class="n">lintLHsBinds</span><span class="w"> </span><span class="n">lbinds</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">tcEnv</span>
<span class="nf">lintLHsBinds</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">LHsBinds</span><span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">GhcTc</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">lintLHsBinds</span><span class="w"> </span><span class="n">lbinds</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sequence_</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">listify</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">lbinds</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">L</span><span class="w"> </span><span class="n">loc</span><span class="w"> </span><span class="n">expr</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">HsWrap</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">L</span><span class="w"> </span><span class="n">loc</span><span class="w"> </span><span class="n">e</span>
<span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">HsOverLit</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">lintHsOverLit</span><span class="w"> </span><span class="n">loc</span><span class="w"> </span><span class="n">l</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Nothing</span>
<span class="nf">listify</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Typeable</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="p">(</span><span class="n">r</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">SYB</span><span class="o">.</span><span class="kt">GenericQ</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="nf">listify</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">SYB</span><span class="o">.</span><span class="n">everything</span><span class="w"> </span><span class="p">(</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="p">`</span><span class="kt">SYB</span><span class="o">.</span><span class="n">mkQ</span><span class="p">`</span><span class="w"> </span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">toList</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span>
<span class="nf">lintHsOverLit</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">SrcSpan</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">HsOverLit</span><span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">GhcTc</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">lintHsOverLit</span><span class="w"> </span><span class="n">loc</span><span class="w"> </span><span class="n">lit</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">doSomething</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">listify</tt> は与えられた <tt class="docutils literal">Data</tt> のインスタンスのデータ型を再帰的に辿り,該当するデータ型の部分を見つけたら与えられた関数を適用し,適用結果をリストで集約して返す.これを使って, <tt class="docutils literal">LHsExpr GhcTc</tt> の部分の探索を行なっている. <tt class="docutils literal">LHsExpr GhcTc</tt> は式を表す型 <tt class="docutils literal">HsExpr GhcTc</tt> にソースの位置情報がついたものになっている. <tt class="docutils literal">HsExpr a</tt> のうち,リテラルに関するコンストラクタは次のものになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">HsExpr</span><span class="w"> </span><span class="n">p</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">HsLit</span><span class="w"> </span><span class="p">(</span><span class="kt">XLitE</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">HsLit</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">HsOverLit</span><span class="w"> </span><span class="p">(</span><span class="kt">XOverLitE</span><span class="w"> </span><span class="n">p</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">HsOverLit</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="o">...</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">HsLit</tt> はオーバーロードされていないリテラル,例えば unboxed なリテラルや <tt class="docutils literal">OverloadedStrings</tt> 拡張のない環境下での文字列リテラルなどを表す. <tt class="docutils literal">HsOverLit</tt> は逆にオーバーロードされたリテラルを表す. <tt class="docutils literal">X~</tt> みたいな部分は <a class="reference external" href="https://www.microsoft.com/en-us/research/publication/trees-that-grow/">Trees that Grow</a> の実装部分.後からコンストラクタを拡張したり,フェーズによって情報を付加したりできるようになっている.まあ,だいたいは無視して良くて, <tt class="docutils literal">HsOverLit</tt> コンストラクタの本体は <tt class="docutils literal">HsOverLit p</tt> の部分.中身は,次のようになっている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">HsOverLit</span><span class="w"> </span><span class="n">p</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">OverLit</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">ol_ext</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">XOverLit</span><span class="w"> </span><span class="n">p</span><span class="p">,</span>
<span class="w"> </span><span class="n">ol_val</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">OverLitVal</span><span class="p">,</span>
<span class="w"> </span><span class="n">ol_witness</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">HsExpr</span><span class="w"> </span><span class="n">p</span><span class="p">}</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">XOverLit</span><span class="w"> </span><span class="p">(</span><span class="kt">XXOverLit</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">XOverLit</tt> コンストラクタの部分はやっぱり <a class="reference external" href="https://www.microsoft.com/en-us/research/publication/trees-that-grow/">Trees that Grow</a> の部分になっていて,現在はまだ使われていない.なので, <tt class="docutils literal">OverLit</tt> コンストラクタが主要部分になる.それぞれのフィールドは,</p>
<dl class="docutils">
<dt><tt class="docutils literal">ol_ext</tt></dt>
<dd><a class="reference external" href="https://www.microsoft.com/en-us/research/publication/trees-that-grow/">Trees that Grow</a> の適用部分.型検査後はリテラルの型が入っている.</dd>
<dt><tt class="docutils literal">ol_val</tt></dt>
<dd>本体.リテラルの内容が入っている.</dd>
<dt><tt class="docutils literal">ol_witness</tt></dt>
<dd>脱糖先として想定される式の AST が入っている.例えば文字列リテラル <tt class="docutils literal">"str"</tt> なら <tt class="docutils literal">fromString "str"</tt> みたいなもの.</dd>
</dl>
<p>みたいな感じ. <tt class="docutils literal">ol_val</tt> の中身は</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">OverLitVal</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">HsIntegral</span><span class="w"> </span><span class="o">!</span><span class="kt">IntegralLit</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">HsFractional</span><span class="w"> </span><span class="o">!</span><span class="kt">FractionalLit</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">HsIsString</span><span class="w"> </span><span class="o">!</span><span class="kt">SourceText</span><span class="w"> </span><span class="o">!</span><span class="kt">FastString</span>
</pre></div></td></tr></table></div>
<p>とほぼそのままの形の物が入っている. <tt class="docutils literal">FastString</tt> は GHC 内部で使用されている文字列を表すためのデータ型で,中身はちょっと情報を付加した <tt class="docutils literal">ByteString</tt> になる.今回の場合は UTF-8 エンコードされたリテラルの文字列が入っている.</p>
</div>
<div class="section" id="bytestring">
<h2>ByteString リテラルをチェックする<a class="headerlink" href="#bytestring" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>後はこのリテラル情報を適当にチェックすれば良い.例えば, <tt class="docutils literal">ByteString</tt> のリテラルをチェックしてみる.まず,概形は以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="nn">Control.Monad</span>
<span class="nf">lintHsOverLit</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">SrcSpan</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">HsOverLit</span><span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">GhcTc</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">lintHsOverLit</span><span class="w"> </span><span class="n">loc</span><span class="w"> </span><span class="n">lit</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">lit</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">OverLit</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="n">ol_val</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">HsIsString</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">l</span><span class="p">,</span>
<span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="n">ol_ext</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">HsSyn</span><span class="o">.</span><span class="kt">OverLitTc</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">ty</span><span class="p">}</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">ty</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">ty</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">checkValidLiteral</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">ty</span>
<span class="w"> </span><span class="n">unless</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">throwWarning</span><span class="w"> </span><span class="n">l</span>
<span class="w"> </span><span class="n">checkValidLiteral</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">FastString</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">Type</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="n">checkValidLiteral</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">ty</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">doSomething</span>
<span class="w"> </span><span class="n">throwWarning</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">FastString</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="n">throwWarning</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">doSomething</span>
</pre></div></td></tr></table></div>
<p>後は, <tt class="docutils literal">ByteString</tt> の正常なリテラルかを判定する <tt class="docutils literal">checkValidLiteral</tt> と,警告を発生させる <tt class="docutils literal">throwWarning</tt> をそれぞれ実装していく. <tt class="docutils literal">checkValidLiteral</tt> の概形は以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Data.Char</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">Char</span>
<span class="nf">checkValidLiteral</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">FastString</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">Type</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">checkValidLiteral</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="n">ty</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">tyConAppTyCon_maybe</span><span class="w"> </span><span class="n">ty</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">Nothing</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="n">tc</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">isByteStringTyCon</span><span class="w"> </span><span class="n">tc</span>
<span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">isValidByteStringLiteral</span><span class="w"> </span><span class="n">l</span>
<span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">isByteStringTyCon</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">TyCon</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="n">isByteStringTyCon</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">doSomething</span>
<span class="w"> </span><span class="n">isValidByteStringLiteral</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">FastString</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Bool</span>
<span class="w"> </span><span class="n">isValidByteStringLiteral</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">all</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">c</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Char</span><span class="o">.</span><span class="n">ord</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="mi">256</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">unpackFS</span><span class="w"> </span><span class="n">l</span>
</pre></div></td></tr></table></div>
<p>流れとしては,</p>
<ol class="arabic simple">
<li>リテラルの型を見て,その型が具体的な型でかつ</li>
<li><tt class="docutils literal">ByteString</tt> の型コンストラクタで構築されている時,</li>
<li>8bit の文字だけで構築されている場合</li>
</ol>
<p>真を返すようにしている. <tt class="docutils literal">isByteStringTyCon</tt> では <tt class="docutils literal">ByteString</tt> の型コンストラクタかを判定する必要がある.この操作はちょっとめんどくさくて,以下のような実装になる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">TcRnMonad</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">TcM</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Finder</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">IfaceEnv</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Control.Monad.IO.Class</span>
<span class="nf">isByteStringTyCon</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">TyCon</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">isByteStringTyCon</span><span class="w"> </span><span class="n">tc</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">tns</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">findByteStringTyConNames</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">elem</span><span class="w"> </span><span class="p">(</span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">tyConName</span><span class="w"> </span><span class="n">tyCon</span><span class="p">)</span><span class="w"> </span><span class="n">tns</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">findByteStringTyConNames</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">traverse</span><span class="w"> </span><span class="n">findByteStringTyConNameByModule</span>
<span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s">"Data.ByteString.Internal"</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="s">"Data.ByteString.Lazy.Internal"</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="n">findByteStringTyConNameByModule</span><span class="w"> </span><span class="n">moduleName</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">hscEnv</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="n">getTopEnv</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">mn</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">mkModuleName</span><span class="w"> </span><span class="n">moduleName</span>
<span class="w"> </span><span class="n">fr</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">liftIO</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Finder</span><span class="o">.</span><span class="n">findImportedModule</span><span class="w"> </span><span class="n">hscEnv</span><span class="w"> </span><span class="n">mn</span><span class="w"> </span><span class="n">bytestringPackage</span>
<span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">fr</span><span class="w"> </span><span class="kr">of</span>
<span class="w"> </span><span class="kt">Finder</span><span class="o">.</span><span class="kt">Found</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="n">md</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">tn</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">IfaceEnv</span><span class="o">.</span><span class="n">lookupOrig</span><span class="w"> </span><span class="n">md</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">mkTcOcc</span><span class="w"> </span><span class="s">"ByteString"</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="n">tn</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="kt">Nothing</span>
<span class="w"> </span><span class="n">bytestringPackage</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">fsLit</span><span class="w"> </span><span class="s">"bytestring"</span>
</pre></div></td></tr></table></div>
<p>このような実装で,依存している <tt class="docutils literal">bytestring</tt> パッケージのモジュールから, <tt class="docutils literal">ByteString</tt> という名前だった型名のものをうまく探し出して,型コンストラクタの名前がその名前と一致するかをチェックすることができる.<tt class="docutils literal">TcM</tt> モナドは, <tt class="docutils literal">MonadIO</tt> のインスタンスなので, <tt class="docutils literal">IO</tt> 操作を普通に実行できる.なので,必要な操作が <tt class="docutils literal">TcM</tt> の操作で見つからなかったら, <tt class="docutils literal">IO</tt> の操作を探してみるか自分で実装するかすると良い.これで <tt class="docutils literal">checkValidLiteral</tt> は実装できたので,後は警告を出す部分を実装する. <tt class="docutils literal">throwWarning</tt> の実装は以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE OverloadedStrings #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Bag</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">ErrUtils</span>
<span class="nf">throwWarning</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="kt">FastString</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TcM</span><span class="o">.</span><span class="kt">TcM</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">throwWarning</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">dynFlags</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">getDynFlags</span>
<span class="w"> </span><span class="n">liftIO</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">printOrThrowWarnings</span><span class="w"> </span><span class="n">dynFlags</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">warnMsgs</span><span class="w"> </span><span class="n">dynFlags</span><span class="w"> </span><span class="n">l</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">warnMsgs</span><span class="w"> </span><span class="n">dynFlags</span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="ow">=</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">errDoc</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">ErrUtils</span><span class="o">.</span><span class="n">errDoc</span>
<span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">ftext</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="s">"Literal </span><span class="se">\"</span><span class="s">"</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="n">l</span><span class="w"> </span><span class="o"><></span><span class="w"> </span><span class="s">"</span><span class="se">\"</span><span class="s"> contains illegal characters for ByteString"</span><span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="kt">GhcPlugins</span><span class="o">.</span><span class="n">text</span><span class="w"> </span><span class="s">"Avoid to use non-8bit characters or may use Text instead."</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="n">msg</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">ErrUtils</span><span class="o">.</span><span class="n">formatErrDoc</span><span class="w"> </span><span class="n">dynFlags</span><span class="w"> </span><span class="n">errDoc</span>
<span class="w"> </span><span class="n">warnMsg</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">ErrUtils</span><span class="o">.</span><span class="n">mkPlainWarnMsg</span><span class="w"> </span><span class="n">dynFlags</span><span class="w"> </span><span class="n">loc</span><span class="w"> </span><span class="n">msg</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="kt">Bag</span><span class="o">.</span><span class="n">unitBag</span><span class="w"> </span><span class="n">warnMsg</span>
</pre></div></td></tr></table></div>
<p>単純に警告を一つ作ってそれを投げてるだけ. <tt class="docutils literal">Bag</tt> は GHC 内で使われている順序なしのコレクションで,内部は単なる二分木になっていて,挿入や結合が定数時間のデータ構造になっている.これで警告のコレクションを作って, <tt class="docutils literal">printOrThrowWarnings</tt> に渡すと,警告の内容を見ていい感じに出力をしたりコンパイルを中断したりしてくれる.以上で実装できる.このプラグインを次のような例</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE OverloadedStrings #-}</span>
<span class="kr">module</span><span class="w"> </span><span class="nn">Main</span><span class="w"> </span><span class="kr">where</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Data.ByteString.Char8</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">Char8</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Data.ByteString.Lazy.Char8</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">LazyChar8</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">System.IO</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">System</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">putBSStrLn</span><span class="w"> </span><span class="s">"ascii string"</span>
<span class="w"> </span><span class="n">putBSStrLn</span><span class="w"> </span><span class="s">"のっとばいとすとりんぐ"</span>
<span class="w"> </span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"すとりんぐ"</span>
<span class="w"> </span><span class="n">putLBSStrLn</span><span class="w"> </span><span class="s">"のっとれいじーばいとすとりんぐ"</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">putBSStrLn</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Char8</span><span class="o">.</span><span class="n">hPutStrLn</span><span class="w"> </span><span class="kt">System</span><span class="o">.</span><span class="n">stdout</span>
<span class="w"> </span><span class="n">putLBSStrLn</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">LazyChar8</span><span class="o">.</span><span class="n">hPutStrLn</span><span class="w"> </span><span class="kt">System</span><span class="o">.</span><span class="n">stdout</span>
</pre></div></td></tr></table></div>
<p>で動かしてみると,以下のような出力が得られる:</p>
<pre class="literal-block">
Main.hs:12:16: warning:
• Literal "のっとばいとすとりんぐ" contains illegal characters for ByteString
• Avoid to use non-8bit characters or may use Text instead.
|
12 | putBSStrLn "のっとばいとすとりんぐ"
| ^^^^^^^^^^^^^
Main.hs:14:17: warning:
• Literal "のっとれいじーばいとすとりんぐ" contains illegal characters for ByteString
• Avoid to use non-8bit characters or may use Text instead.
|
14 | putLBSStrLn "のっとれいじーばいとすとりんぐ"
| ^^^^^^^^^^^^^^^^^
</pre>
<p>なお,解説のコードとはちょっと違うが, <tt class="docutils literal">ByteString</tt> のリテラルをチェックするプラグインの全体は, <a class="reference external" href="https://github.com/mizunashi-mana/ghc-bslit-linter">https://github.com/mizunashi-mana/ghc-bslit-linter</a> に上がっているので参考にして欲しい.</p>
</div>
<div class="section" id="auto-id-2">
<h2>まとめ<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>GHC Compiler Plugin の新しく導入された Source Plugin を使って,リテラルをコンパイル時に検査する手法を紹介した.式を全部探索することになるので,でかいソースにかける場合コンパイル時間の増加が気になるところだが,一応こういうことができるよという感じ.ただ,プラグインを書くにはそれなりに GHC 内のノウハウを知る必要がある.</p>
<p>Source Plugin を使うと,初心者向けに警告メッセージを分かりやすくしたり増やしたりすることもできそうだ.メンテするのは大変かもしれないけど, SYB などを使えばそれなりに持続期間の長いプラグインは作れるかもしれない.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/10/lint-bslit-by-ghc-plugin.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/10/lint-bslit-by-ghc-plugin.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>iptables から nftables への移行2019-09-20T22:10:24+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-09-20:/blog/posts/2019/09/nftables-on-debian/<p>Debian GNU/Linux 10 ,コードネーム buster が安定板リリースを迎え結構経ったので,そろそろアップグレード案件やるかみたいな感 …</p><p>Debian GNU/Linux 10 ,コードネーム buster が安定板リリースを迎え結構経ったので,そろそろアップグレード案件やるかみたいな感じになった.</p>
<p>さて, buster からは iptables に代わり nftables が採用されている.なので, iptables から nftables に移行が推奨されている.で,既存の iptables のルールセットを nftables 用に書き直したので,その備忘録.</p>
<p>なお,参考文献は以下だが,こちとらインフラは素人の普段はプログラマ屋さんなので結構間違ってるかもしれない.</p>
<ul class="simple">
<li><a class="reference external" href="https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes">https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes</a></li>
<li><a class="reference external" href="https://wiki.archlinux.jp/index.php/Nftables">https://wiki.archlinux.jp/index.php/Nftables</a></li>
</ul>
<div class="section" id="nftables">
<h2>nftables の基本<a class="headerlink" href="#nftables" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>nftables はそこまで iptables と基本は変わらなくて,文法とかが異なったり永続化の方法がデフォルトで付いてたりとユーザ操作部分が分かりやすくなったっぽい.基本的には,</p>
<ul class="simple">
<li><tt class="docutils literal">nft</tt> コマンドで操作</li>
<li><tt class="docutils literal">/etc/nftables.conf</tt> で永続化</li>
</ul>
<p>みたいな感じ. <tt class="docutils literal">nft</tt> は <tt class="docutils literal">sbin</tt> にあるので,ルート権限で参照する必要がある.後,一応 Debian 10 では <tt class="docutils literal">iptables</tt> の互換インターフェースと <tt class="docutils literal">iptables</tt> からの移行用として <tt class="docutils literal"><span class="pre">iptables-translate</span></tt> というコマンドが用意されている.</p>
<p>なお, <tt class="docutils literal">/etc/nftables.conf</tt> の読み込みは systemd のユニットファイルで指定されていて,再読み込みは,</p>
<pre class="literal-block">
systemctl restart nftables
</pre>
<p>でできる.設定ファイルのチェックは,</p>
<pre class="literal-block">
nft -c -f /etc/nftables.conf
</pre>
<p>でできる.現在の設定は,</p>
<pre class="literal-block">
nft list tables
nft list table inet filter
</pre>
<p>とかで確認できる. <tt class="docutils literal">inet filter</tt> テーブルは, <tt class="docutils literal">iptables</tt> の <tt class="docutils literal">filter</tt> と対応する. <tt class="docutils literal"><span class="pre">iptables-translate</span></tt> は <tt class="docutils literal">iptables</tt> のルールを <tt class="docutils literal">nftables</tt> 用に変換してくれるコマンドで,</p>
<pre class="literal-block">
$ iptables-translate -A INPUT -m state --state NEW -j DROP
nft add rule ip filter INPUT ct state new counter drop
</pre>
<p>みたいな感じで使える.なお,一括で変換する <tt class="docutils literal"><span class="pre">iptables-restore-translate</span></tt> も用意されてるっぽい. <tt class="docutils literal"><span class="pre">-f</span></tt> オプションでファイル指定もできる. <tt class="docutils literal">iptables</tt> からの移行の際は,</p>
<ol class="arabic simple">
<li>今のルールを <tt class="docutils literal"><span class="pre">iptables-save</span></tt> で吐き出させて</li>
<li><tt class="docutils literal"><span class="pre">iptables-restore-translate</span></tt> に噛ませて変換し,その変換したルールを実行し</li>
<li>最後に <tt class="docutils literal">nft list ruleset</tt> の内容を <tt class="docutils literal">/etc/nftables.conf</tt> に保存する</li>
</ol>
<p>を実行すれば良い.まあちょっと調整は必要かもしれないけど.</p>
</div>
<div class="section" id="auto-id-1">
<h2>nftables のルール<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて, <tt class="docutils literal">nftables</tt> では <tt class="docutils literal">iptables</tt> のルールから文法が大きく変わった.ただ要素自体はそれほど変化はなさそう.ルールは階層構造で管理されていて,</p>
<ol class="arabic simple">
<li>table family (<tt class="docutils literal">inet</tt> / <tt class="docutils literal">bridge</tt> / etc.)</li>
<li>table type (<tt class="docutils literal">filter</tt> / <tt class="docutils literal">nat</tt> / etc.)</li>
<li>chain (<tt class="docutils literal">input</tt> / <tt class="docutils literal">forward</tt> / <tt class="docutils literal">output</tt> / etc.)</li>
</ol>
<p>の順で指定できる.それぞれ多分好きに増やせるはず. <tt class="docutils literal">/etc/nftables.conf</tt> だと以下のように階層構造で指定できる:</p>
<pre class="literal-block">
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
...
}
chain forward {
type filter hook forward priority 0; policy drop;
...
}
chain output {
type filter hook output priority 0; policy accept;
...
}
}
</pre>
<p>chain は上記のようにそれぞれフックを設定することもできる.後, <tt class="docutils literal">policy</tt> でデフォルトのコントロールフローを設定できる.コントロールフローは以下の種類がある <a class="footnote-reference" href="#queue-operation" id="auto-id-2">[1]</a>:</p>
<dl class="docutils">
<dt>accept</dt>
<dd>パケットを通し,その場でルール評価を終了する</dd>
<dt>drop</dt>
<dd>パケットを落とし,その場でルール評価を終了する</dd>
<dt>continue</dt>
<dd>ルール評価を続ける</dd>
<dt>return</dt>
<dd>現在の chain から呼び出し元の chain に戻って続きを評価する.なお,コールスタックに何もない場合 accept と同じになる</dd>
<dt>jump <chain></dt>
<dd>コールスタックに現在の chain の場所を追加し,指定した chain の評価を始める</dd>
<dt>goto <chain></dt>
<dd>コールスタックに何も追加しないで,指定した chain の評価を始める</dd>
</dl>
<p>で,それぞれ文の最後に指定できる. <tt class="docutils literal">type</tt> と <tt class="docutils literal">policy</tt> は特別な文で,他の文は次のような形をとる:</p>
<pre class="literal-block">
<match>* <statement>* <controlflow>
</pre>
<p><tt class="docutils literal"><match></tt> は文でハンドルするパケットの種類を指定し, <tt class="docutils literal"><statement></tt> はパケットに対する操作を指定できる. <tt class="docutils literal"><match></tt> は,</p>
<dl class="docutils">
<dt>meta</dt>
<dd>パケットのメタデータに対するマッチ</dd>
<dt>ip</dt>
<dd>IP パケットに対するマッチ</dd>
<dt>ip6</dt>
<dd>IPv6 パケットに対するマッチ</dd>
<dt>icmp</dt>
<dd>ICMP パケットに対するマッチ</dd>
<dt>icmpv6</dt>
<dd>ICMPv6 パケットに対するマッチ</dd>
<dt>tcp</dt>
<dd>TCP パケットに対するマッチ</dd>
<dt>udp</dt>
<dd>UDP パケットに対するマッチ</dd>
<dt>ct</dt>
<dd>conntrack エントリに対するマッチ</dd>
</dl>
<p>などのマッチが指定できる.マッチそれぞれにパラメータがあり,より詳細にハンドル文が書ける.例えば, <tt class="docutils literal">ip</tt> マッチは <tt class="docutils literal">saddr</tt> / <tt class="docutils literal">protocol</tt> などのパラメータがあり,以下のような指定が書ける:</p>
<pre class="literal-block">
ip protocol { tcp, udp } ip saddr != 192.168.2.0/24
</pre>
<p>パラメータに対するマッチは,幾つかの関係演算子が使えるようになっていて, <tt class="docutils literal">==</tt> / <tt class="docutils literal">!=</tt> / <tt class="docutils literal"><</tt> などが使えるっぽい.なお,何も指定しないで空白区切で並べると,内部で implicit 演算子扱いになり,それぞれのパラメータでデフォルトの演算子 (大抵は <tt class="docutils literal">==</tt> と同値) が指定されるっぽい.なので,上のは次のと同じ:</p>
<pre class="literal-block">
ip protocol == { tcp, udp } ip saddr != 192.168.2.0/24
</pre>
<p>どのマッチでどのパラメータが使えるのかは, <a class="reference external" href="https://www.netfilter.org/projects/nftables/manpage.html">nftables の man</a> か <a class="reference external" href="https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Matches">Quick reference</a> を参照すれば良い.</p>
<p><tt class="docutils literal"><statement></tt> の方は,</p>
<dl class="docutils">
<dt>log</dt>
<dd>ログ出力を行う</dd>
<dt>reject</dt>
<dd>レスポンスパケットを指定して,パケットを落とす</dd>
<dt>counter</dt>
<dd>パケットの数のカウンタを設定する</dd>
<dt>limit</dt>
<dd>パケットのレート制限を設定する</dd>
</dl>
<p>みたいなものが設定できる.それぞれ指定できるパラメータは, <a class="reference external" href="https://www.netfilter.org/projects/nftables/manpage.html">nftables の man</a> か <a class="reference external" href="https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Statements">Quick reference</a> を参照.まあ, <tt class="docutils literal">iptables</tt> と大体同じことができる.</p>
<p>後, <tt class="docutils literal">hashlimit</tt> の代替として <tt class="docutils literal">meter</tt> という機能があるらしいが,現在は代わりに dynamic set / map と言うことになってるらしく,この辺もよく分かってない.時間あるときに調べないと.</p>
</div>
<div class="section" id="auto-id-4">
<h2>設定例<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>とりあえず,今回作った簡単なファイアウォール設定を置いとく:</p>
<pre class="literal-block">
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority 0;
# default drop
policy drop;
# established/related connections
ct state { established, related } accept;
# loopback interface
iif lo accept;
jump filter_broadcast;
jump filter_fragments;
jump filter_invalids;
jump filter_icmp;
jump filter_synflood;
jump reject_auth_ident;
# accept TCP ports
# SSH
tcp dport { ssh } ct state new accept;
# Web
#tcp dport { http, https } ct state new accept;
# Mail
#tcp dport { smtp } ct state new accept;
jump drop_others;
}
chain forward {
type filter hook forward priority 0;
# default drop
policy drop;
# established/related connections
ct state { established, related } accept;
# loopback interface
iif lo accept;
}
chain output {
type filter hook output priority 0;
# default accept
policy accept;
}
chain filter_broadcast {
pkttype != { broadcast, multicast } return;
drop;
}
chain filter_fragments {
ip frag-off & 0x1fff 0 return;
limit rate 6/minute burst 10 packets log prefix "[IPTABLES FRAGMENT]: " level debug continue;
drop;
}
chain filter_invalids {
ct state != invalid return;
limit rate 6/minute burst 10 packets log prefix "[IPTABLES INVALID]: " level debug continue;
drop;
}
chain filter_icmp {
icmpv6 type {
destination-unreachable,
packet-too-big,
time-exceeded,
parameter-problem,
nd-router-advert,
nd-neighbor-solicit,
nd-neighbor-advert,
} accept;
icmp type {
destination-unreachable,
router-advertisement,
time-exceeded,
parameter-problem,
} accept;
# echo-request
jump filter_pingdeath;
icmp type echo-request accept;
}
chain filter_pingdeath {
icmp type != echo-request return;
meter ping_scan { ip saddr limit rate 1/second burst 4 packets } return;
limit rate 6/minute burst 10 packets log prefix "[IPTABLES PING_DEATH]: " level debug continue;
drop;
}
chain filter_synflood {
ct state != new return;
meter syn_scan { ip saddr limit rate 2/second burst 100 packets } return;
limit rate 6/minute burst 10 packets log prefix "[IPTABLES SYNFLOOD]: " level debug continue;
drop;
}
chain drop_others {
limit rate 6/minute burst 10 packets log prefix "[IPTABLES SCANED]: " level debug continue;
drop;
}
chain reject_auth_ident {
tcp dport { 113 } reject with tcp reset;
}
}
</pre>
<p>うちの環境は, IPv6 無効にしてるので IPv6 用には他にも色々書いといたほうがいいかもしれない.</p>
</div>
<div class="section" id="auto-id-5">
<h2>まとめ<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Debian buster にアップグレードした時の備忘録でした. <tt class="docutils literal">iptables</tt> の諸々が改善されたのは良いが,結局よく分からん文法になってて,うーんと言う感じ.まあ,設定ファイルは前よりずっと見やすくなった感はある.ただ, <tt class="docutils literal">nftables</tt> の文法,形式的なものが見つからなくてドキュメントもかなりゆるふわ感があり,結局本家の bison ファイルみに行く羽目になったのでそこら辺何とかして欲しいっすね.こちらからは以上です.</p>
<table class="docutils footnote" frame="void" id="queue-operation" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><tt class="docutils literal">queue</tt> という操作もあるようだけど,あんまり深く調べてない.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/09/nftables-on-debian.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/09/nftables-on-debian.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Scala の Map.flatMap の罠2019-09-03T12:07:45+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-09-03:/blog/posts/2019/09/scala-map-flatmap-trap/<p>Scala のコレクションライブラリは難しい.最近,強くそう思える事案に出くわしたので,そのメモ.なお,使った環境は以下 …</p><p>Scala のコレクションライブラリは難しい.最近,強くそう思える事案に出くわしたので,そのメモ.なお,使った環境は以下の通り:</p>
<table border="1" class="docutils">
<colgroup>
<col width="39%"/>
<col width="61%"/>
</colgroup>
<tbody valign="top">
<tr><td>Scala のバージョン</td>
<td>2.13.0</td>
</tr>
<tr><td>Java Runtime のバージョン</td>
<td>Java(TM) SE Runtime Environment 1.8.0_131</td>
</tr>
<tr><td>Java Hotspot のバージョン</td>
<td>Java HotSpot(TM) 64-Bit Server VM 25.131</td>
</tr>
</tbody>
</table>
<div class="section" id="auto-id-1">
<h2>出くわした謎挙動<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>次のプログラムの結果は何になるだろうか?</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)),</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">3</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(),</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">5</span><span class="p">)),</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">vs</span><span class="p">)</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">m</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">vs</span>
<span class="p">}</span><span class="w"> </span><span class="k">yield</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>自分はこのプログラムを以下の結果が得られると期待して書いた:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nc">List</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">)):</span><span class="w"> </span><span class="nc">Seq</span><span class="p">[(</span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">Int</span><span class="p">)]</span>
</pre></div></td></tr></table></div>
<p>しかし,実際に得られるのは次の結果だ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nc">List</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">4</span><span class="p">),</span><span class="w"> </span><span class="p">(</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">)):</span><span class="w"> </span><span class="nc">Seq</span><span class="p">[(</span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">Int</span><span class="p">)]</span>
</pre></div></td></tr></table></div>
<p>このプログラムで自分が意図したことは, <tt class="docutils literal">Map</tt> の要素の配列をフラットにして,キーと結びつけて返すことだが,何か良からぬ力が働いて,実際には <tt class="docutils literal">Map</tt> の最後の要素しか取得できていない.</p>
<p>もう一問.次のプログラムの結果は何になるだろうか?</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)),</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">3</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(),</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">5</span><span class="p">)),</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">vs</span><span class="p">)</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">m</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">vs</span>
<span class="p">}</span><span class="w"> </span><span class="k">yield</span><span class="w"> </span><span class="n">v</span>
</pre></div></td></tr></table></div>
<p>さっきと変わったのは <tt class="docutils literal">k</tt> を結果に使わなかっただけ.実際に動かすと,次の結果が得られる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nc">List</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">5</span><span class="p">):</span><span class="w"> </span><span class="nc">Seq</span><span class="p">[</span><span class="nc">Int</span><span class="p">]</span>
</pre></div></td></tr></table></div>
<p>この結果は意図通りになった.今回は全要素を全てフラットにできているようだ.さて,先ほどのプログラムの違いはなんなのだろうか?</p>
</div>
<div class="section" id="auto-id-2">
<h2>種明かし<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal"><span class="pre">for-yield</span></tt> は, <tt class="docutils literal">flatMap</tt> , <tt class="docutils literal">map</tt> , <tt class="docutils literal">withFilter</tt> (または <tt class="docutils literal">filter</tt>) を使ったコードに変換される糖衣構文だ.先ほどのプログラムは次のプログラムと一致する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="nc">Seq</span><span class="p">(</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)),</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">3</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(),</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">5</span><span class="p">)),</span>
<span class="p">).</span><span class="n">flatMap</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o">=></span>
<span class="w"> </span><span class="n">m</span><span class="p">.</span><span class="n">flatMap</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">vs</span><span class="p">)</span><span class="w"> </span><span class="o">=></span>
<span class="w"> </span><span class="n">vs</span><span class="p">.</span><span class="n">map</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>さて,この2個目の <tt class="docutils literal">flatMap</tt> に注目してみる.こいつが何を返しているか調べてみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">scala</span><span class="o">></span><span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)).</span><span class="n">flatMap</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">vs</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">vs</span><span class="p">.</span><span class="n">map</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span>
<span class="n">res0</span><span class="p">:</span><span class="w"> </span><span class="n">scala</span><span class="p">.</span><span class="n">collection</span><span class="p">.</span><span class="n">immutable</span><span class="p">.</span><span class="nc">Map</span><span class="p">[</span><span class="nc">Int</span><span class="p">,</span><span class="nc">Int</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="mi">4</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>皆さん原因が分かったと思うが,2個目の <tt class="docutils literal">flatMap</tt> が生成するのは <tt class="docutils literal">Map</tt> だ.その実装は, <tt class="docutils literal"><span class="pre">IterableOnce[(K,</span> V)]</tt> を受け取ると,それぞれのタプルの一つ目をキー,二つ目を値だと思って,どんどん空の <tt class="docutils literal">Map</tt> に追加していく <a class="footnote-reference" href="#map-builder-impl" id="auto-id-3">[1]</a> .なので,キーごとに最後に書き込まれた値だけが残るというわけだ.後は, <tt class="docutils literal">Map[K, V]</tt> 自体は <tt class="docutils literal"><span class="pre">Iterable[(K,</span> V)]</tt> というトレイト条件を満たすので, <tt class="docutils literal">Seq[V1]</tt> の <tt class="docutils literal">flatMap: (V1 => IterableOnce[V2]) => Seq[V2]</tt> によってタプルを要素に持つ <tt class="docutils literal">Seq</tt> データとして,結果が構築される.</p>
<p>ところで,二問目の結果はこれでは説明がつかない.こちらはなぜ全ての要素が消えずに残るのだろう? 実は, <tt class="docutils literal">Map[K, V]</tt> に対しての <tt class="docutils literal">flatMap</tt> は,オーバーロードされた以下の2通りの実装があり,結果の型によってどちらかが選ばれる <a class="footnote-reference" href="#iterableonce-flatmap" id="auto-id-4">[2]</a> .</p>
<ul class="simple">
<li><tt class="docutils literal">MapOps</tt> の <tt class="docutils literal">flatMap[K2, <span class="pre">V2](f:</span> ((K, V)) => <span class="pre">IterableOnce[(K2,</span> <span class="pre">V2)]):</span> Map[K, V]</tt></li>
<li><tt class="docutils literal">IterableOps</tt> の <tt class="docutils literal"><span class="pre">flatMap[B](f:</span> (K, V) => <span class="pre">IterableOnce[B]):</span> Iterable[B]</tt></li>
</ul>
<p>一つ目のプログラムではタプルを返しているので <tt class="docutils literal">MapOps</tt> のものが,二つ目では <tt class="docutils literal">IterableOps</tt> のものが使われている. <tt class="docutils literal">IterableOps</tt> のものが自分が意図したものだが,一つ目のものは <tt class="docutils literal">MapOps</tt> の <tt class="docutils literal">flatMap</tt> が呼ばれていたため,一見不思議な動作になったと言うわけだ.</p>
<p>なおこの動作につまづいた時,以下のように書き換えても同じ動作をすることが不思議だった:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)),</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">3</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(),</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">5</span><span class="p">)),</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">vs</span><span class="p">)</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">m</span><span class="p">.</span><span class="n">toIterable</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">vs</span>
<span class="p">}</span><span class="w"> </span><span class="k">yield</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>よく分かってないのだけど, <tt class="docutils literal">toIterable</tt> はデフォルトでは単に自身をその型のまま返すらしく, <tt class="docutils literal">Map</tt> もそれを踏襲しているため何の意味もないっぽい.実際にこのプログラムを意図した動作にしたい場合,次のような修正が考えられる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">1</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)),</span>
<span class="w"> </span><span class="nc">Map</span><span class="p">(</span><span class="mi">3</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(),</span><span class="w"> </span><span class="mi">4</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="nc">Seq</span><span class="p">(</span><span class="mi">5</span><span class="p">)),</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">vs</span><span class="p">)</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">Iterable</span><span class="p">[(</span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">Seq</span><span class="p">[</span><span class="nc">Int</span><span class="p">])]</span>
<span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">vs</span>
<span class="p">}</span><span class="w"> </span><span class="k">yield</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>なお,修正方法は他にもいくつかあって,とにかく <tt class="docutils literal">MapOps</tt> の <tt class="docutils literal">flatMap</tt> が選ばれないようにすればいいので,イテレータを返すとかでも回避できる.</p>
</div>
<div class="section" id="auto-id-5">
<h2>まとめ<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Scala のコレクションライブラリむずい.てかこの動作,多分一年後に正確に出力を答えられる自信がない.とりあえず, <tt class="docutils literal">Map</tt> に対して <tt class="docutils literal"><span class="pre">for-yield</span></tt> 使ったり <tt class="docutils literal">flatMap</tt> を他のコレクションと混ぜて使ったりするのはやめたほうが良さそうだなと思った.</p>
<p>後, Intellij さんの Scala プラグインが強くて,上の <tt class="docutils literal">.toIterable</tt> とかの何の意味もないメソッドチェーン使うと灰色にしてくれたり, deprecated なメソッドチェーンは取り消し線引いてくれたりする.ただ, Scala 力が低すぎて <tt class="docutils literal">.toIterable</tt> は何の意味もないよと Intellij さんが教えてくれてるのに,は?んなわけねえだろとか思ってたので,これからは Intellij さんを信じていきたい.こちらからは以上です.</p>
<table class="docutils footnote" frame="void" id="map-builder-impl" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[1]</a></td><td>実際には, <tt class="docutils literal">Map</tt> 用の可変ビルダに突っ込む.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="iterableonce-flatmap" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[2]</a></td><td>実は <tt class="docutils literal">IterableOnce</tt> にも <tt class="docutils literal">flatMap</tt> が生えていて,こちらは deprecated になっている.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/09/scala-map-flatmap-trap.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/09/scala-map-flatmap-trap.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>colimit としての自然数の集合2019-08-30T13:27:06+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-08-30:/blog/posts/2019/08/set-of-natural-numbers-is-colimit/<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo separator="true">;</mo><mi>i</mi><mo>↦</mo><mo stretchy="false">{</mo><mi>n</mi><mo>∣</mo><mi>n</mi><mo>≤</mo><mi>i</mi><mo stretchy="false">}</mo><mo>:</mo><mi mathvariant="double-struck">N</mi><mo>→</mo><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow></mrow><annotation encoding="application/x-tex">F; i \mapsto \{n \mid n \leq i\}: \mathbb{N} \to \mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> みたいな directed diagram を考えた時,こいつの colimit は何に …</p><p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo separator="true">;</mo><mi>i</mi><mo>↦</mo><mo stretchy="false">{</mo><mi>n</mi><mo>∣</mo><mi>n</mi><mo>≤</mo><mi>i</mi><mo stretchy="false">}</mo><mo>:</mo><mi mathvariant="double-struck">N</mi><mo>→</mo><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow></mrow><annotation encoding="application/x-tex">F; i \mapsto \{n \mid n \leq i\}: \mathbb{N} \to \mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> みたいな directed diagram を考えた時,こいつの colimit は何になるか考えようという話が降ってきたんだけど,圏論弱者で頭が混乱してしまって解けなかったので,色々考えたメモ.</p>
<div class="section" id="directed-colimit">
<h2>directed colimit<a class="headerlink" href="#directed-colimit" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ある圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> と圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span></span> からの図式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi>I</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">F: I \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> を考える.この時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> の colimit とは, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> の対象 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo><mrow><mi mathvariant="normal">c</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">m</mi></mrow></mo><mi>F</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">\mathop{\mathrm{colim}} F \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mop"><span class="mord"><span class="mord mathrm">colim</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> と cocone <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi><mo>:</mo><mi>F</mi><mo>⇒</mo><mi mathvariant="normal">Δ</mi><mo stretchy="false">(</mo><mo><mrow><mi mathvariant="normal">c</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">m</mi></mrow></mo><mi>F</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mu: F \Rightarrow \Delta (\mathop{\mathrm{colim}} F)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">μ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">Δ</span><span class="mopen">(</span><span class="mop"><span class="mord"><span class="mord mathrm">colim</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mclose">)</span></span></span></span></span> の組で,以下の普遍性を満たすもの:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>φ</mi><mo>:</mo><mi>F</mi><mo>⇒</mo><mi mathvariant="normal">Δ</mi><mi>X</mi><mo separator="true">.</mo><mi mathvariant="normal">∃</mi><mo stretchy="false">!</mo><mi>f</mi><mo>:</mo><mo><mrow><mi mathvariant="normal">c</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">l</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">m</mi></mrow></mo><mi>F</mi><mo>→</mo><mi>X</mi><mo separator="true">.</mo><mi>μ</mi><mo separator="true">;</mo><mi mathvariant="normal">Δ</mi><mo stretchy="false">(</mo><mi>f</mi><mo stretchy="false">)</mo><mo>=</mo><mi>φ</mi></mrow><annotation encoding="application/x-tex">
\forall \varphi: F \Rightarrow \Delta X\ldotp \exists ! f: \mathop{\mathrm{colim}} F \to X\ldotp \mu; \Delta(f) = \varphi
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∃</span><span class="mclose">!</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mop"><span class="mord"><span class="mord mathrm">colim</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">μ</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Δ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">φ</span></span></span></span></span></div>
<p>ただし, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">Δ</mi><mo>:</mo><mi>C</mi><mo>→</mo><msup><mi>C</mi><mi>I</mi></msup></mrow><annotation encoding="application/x-tex">\Delta: C \to C^I</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8413em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">I</span></span></span></span></span></span></span></span></span></span></span></span> は対角関手.</p>
<p>diagram の index が directed set である場合に,それ上の colimit を directed colimit と呼ぶ.とりあえずここまでが導入.</p>
</div>
<div class="section" id="colimit-mathbb-n">
<h2>colimit としての <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span><a class="headerlink" href="#colimit-mathbb-n" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo separator="true">;</mo><mi>i</mi><mo>→</mo><mo stretchy="false">{</mo><mi>n</mi><mo>∣</mo><mi>n</mi><mo>≤</mo><mi>i</mi><mo stretchy="false">}</mo><mo>:</mo><mi mathvariant="double-struck">N</mi><mo>→</mo><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow></mrow><annotation encoding="application/x-tex">F; i \to \{n \mid n \leq i\}: \mathbb{N} \to \mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> のような diagram を考える.射は単純に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo stretchy="false">(</mo><mi>i</mi><mo>≤</mo><mi>j</mi><mo stretchy="false">)</mo><mo separator="true">;</mo><mi>n</mi><mo>↦</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">F(i \leq j); n \mapsto n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> で作れる.こいつの directed colimit は何になるだろう? 直感的には,最終的に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> に収束しそうだ.確かめてみる.</p>
<p>まず colimit cocone は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>μ</mi><mi>i</mi></msub><mo separator="true">;</mo><mi>x</mi><mo>↦</mo><mi>x</mi><mo>:</mo><mo stretchy="false">{</mo><mi>n</mi><mo>∣</mo><mi>n</mi><mo>≤</mo><mi>i</mi><mo stretchy="false">}</mo><mo>→</mo><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mu_i; x \mapsto x: \{n \mid n \leq i\} \to \mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7054em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> で考えられそうだ.さて, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>φ</mi><mo>:</mo><mi>F</mi><mo>⇒</mo><mi mathvariant="normal">Δ</mi><mi>X</mi></mrow><annotation encoding="application/x-tex">\varphi: F \Rightarrow \Delta X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> に対して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi><mo separator="true">;</mo><mi mathvariant="normal">Δ</mi><mo stretchy="false">(</mo><mi>f</mi><mo stretchy="false">)</mo><mo>=</mo><mi>φ</mi></mrow><annotation encoding="application/x-tex">\mu; \Delta(f) = \varphi</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">μ</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">Δ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">φ</span></span></span></span></span> を満たす <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi mathvariant="double-struck">N</mi><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">f: \mathbb{N} \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> を考えてみる.</p>
<img alt="一意性について,計算している図式." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/08/set-of-natural-numbers-is-colimit/set-of-natural-numbers-is-colimit/poset-colimit-proof.png"/>
<p>つまり任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>φ</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(n) = \varphi_n(n)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">φ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></span> が成り立ち,逆に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>↦</mo><msub><mi>φ</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">n \mapsto \varphi_n(n)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.522em;vertical-align:-0.011em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">φ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></span> を考えればこれは一意で等式を満たす射ということになる.ここから, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> の colimit となる.</p>
</div>
<div class="section" id="cpo-colimit">
<h2>Cpo での colimit<a class="headerlink" href="#cpo-colimit" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて実は本題はここからで, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><mi>n</mi><mo>∣</mo><mi>n</mi><mo>≤</mo><mi>i</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\{n \mid n \leq i\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mclose">}</span></span></span></span></span> は finite poset でありつまり cpo だ.なので先ほどの <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow><annotation encoding="application/x-tex">\mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span> への図式としても考えられる.この場合, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> の colimit は何になるだろう? 問題は, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> は cpo でないことだ. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> 全体を考えると,こいつは directed set になるが sup を持たないからだ.では, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> の colimit は無いのだろうか?</p>
<p>実は, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> は cpo では無いのだが <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">N</mi><mi mathvariant="normal">∞</mi></msub><mo>=</mo><mi mathvariant="double-struck">N</mi><mo>∪</mo><mo stretchy="false">{</mo><mi mathvariant="normal">∞</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\mathbb{N}_{\infty} = \mathbb{N} \cup \{\infty\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">∞</span><span class="mclose">}</span></span></span></span></span> は cpo になる.こいつに対して <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> での構成を試してみる. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> の範囲では同じ話を適用できる.が, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi mathvariant="normal">∞</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(\infty)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord">∞</span><span class="mclose">)</span></span></span></span></span> が一意に決まるかは分からないので, colimit を考えられないように見える.しかし,実はこいつを決められる要素が, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow><annotation encoding="application/x-tex">\mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span> にはある.それが連続性だ.今回の場合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><msub><mi mathvariant="double-struck">N</mi><mi mathvariant="normal">∞</mi></msub><mo>→</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">f: \mathbb{N}_{\infty} \to X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> は連続関数なので,次の式が成り立つ:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi mathvariant="normal">∞</mi><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><munder><mo>⨆</mo><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></munder><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><munder><mo>⨆</mo><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></munder><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><munder><mo>⨆</mo><mrow><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi></mrow></munder><msub><mi>φ</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
f(\infty) = f(\bigsqcup_{n \in \mathbb{N}} n) = \bigsqcup_{n \in \mathbb{N}} f(n) = \bigsqcup_{n \in \mathbb{N}} \varphi_n(n)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord">∞</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3756em;vertical-align:-1.3256em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.8518em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⨆</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.3256em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3756em;vertical-align:-1.3256em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.8518em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⨆</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.3256em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3756em;vertical-align:-1.3256em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.8518em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathbb mtight">N</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⨆</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.3256em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">φ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></span></div>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi></mrow><annotation encoding="application/x-tex">X</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span></span> が cpo なので,こいつは well-defined で sup は一意より, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">N</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{N}_{\infty}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> 全域で一意に定めることができる.ここから, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>:</mo><mi mathvariant="double-struck">N</mi><mo>→</mo><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow></mrow><annotation encoding="application/x-tex">F: \mathbb{N} \to \mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span> の colimit は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">N</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{N}_{\infty}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> になる.</p>
</div>
<div class="section" id="mathrm-poset-mathrm-cpo">
<h2><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow><annotation encoding="application/x-tex">\mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span><a class="headerlink" href="#mathrm-poset-mathrm-cpo" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ここまで見て,混乱した人はいないだろうか? 僕は当初混乱した. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">N</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{N}_{\infty}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow><annotation encoding="application/x-tex">\mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span> で colimit になれるなら,なぜ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> では慣れなかったのだろう? もしかして, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">N</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{N}_{\infty}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> って poset として同型なのか? とか本気で考えた (そんなバカな話はもちろん成り立たない) .なので,最後に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow><annotation encoding="application/x-tex">\mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span> で何が違うのか見てみる.</p>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> の中で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi mathvariant="double-struck">N</mi><mi mathvariant="normal">∞</mi></msub></mrow><annotation encoding="application/x-tex">\mathbb{N}_{\infty}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> への一意射が作れないか考えてみる.先ほどの話から,問題は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi mathvariant="normal">∞</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(\infty)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord">∞</span><span class="mclose">)</span></span></span></span></span> の定め方にあることは分かるだろう.こいつをどう定めるかが問題になるわけだけど, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> の射は単調である必要があるので,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>n</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi><mo separator="true">.</mo><mi>f</mi><mo stretchy="false">(</mo><mi mathvariant="normal">∞</mi><mo stretchy="false">)</mo><mo>≥</mo><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">
\forall n \in \mathbb{N}\ldotp f(\infty) \geq f(n) = n
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathbb">N</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord">∞</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span></div>
<p>を満たす必要がある.ここまでくるとみなさんお気づきだと思うけど, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">\mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> は上限を持たないので,これを満たすように <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span></span> をうまく作れないのだ.これが, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow><annotation encoding="application/x-tex">\mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span> の大きな違いっぽくて, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow><annotation encoding="application/x-tex">\mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span> は directed subset でさえ sup を持てないようなものを除外することで well-defined 性をうまく保証してくれるっぽい.なので,連続性を用いて一意にうまく定めることができるけど, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> ではそこがうまくいかない,一意射の一意性どころか構成できないというわけだ.</p>
</div>
<div class="section" id="auto-id-1">
<h2>まとめ<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>これは完全に知らない話だったので,ほへーってなった.また一つ賢くなってしまった (順序理論界隈とかだと常識かもしれないので,無知を晒してしまったとも言う). <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">C</mi><mi mathvariant="normal">p</mi><mi mathvariant="normal">o</mi></mrow><annotation encoding="application/x-tex">\mathrm{Cpo}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathrm">Cpo</span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">P</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow><annotation encoding="application/x-tex">\mathrm{Poset}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Poset</span></span></span></span></span></span> の full subcategory だと無邪気に信じてたが,こうなると怪しそう.埋め込みうまく作る方法あったりするんだろうか? 時間ができたらちょっと考えてみたい.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/08/set-of-natural-numbers-is-colimit.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/08/set-of-natural-numbers-is-colimit.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Local Do と型クラス2019-07-27T06:47:18+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-07-27:/blog/posts/2019/07/local-do-and-first-type-class/<p>現在, GHC に <a class="reference external" href="https://github.com/ghc-proposals/ghc-proposals/pull/111">線形型の提案</a> がされていて活発に議論されている.プロトタイプも <a class="reference external" href="https://github.com/tweag/ghc/tree/linear-types">ここ</a> から利用可能だ. Docker イメージも利用 …</p><p>現在, GHC に <a class="reference external" href="https://github.com/ghc-proposals/ghc-proposals/pull/111">線形型の提案</a> がされていて活発に議論されている.プロトタイプも <a class="reference external" href="https://github.com/tweag/ghc/tree/linear-types">ここ</a> から利用可能だ. Docker イメージも利用可能なので,気軽に試せると思うので,ぜひ試してみてくれ.</p>
<p>さて,そんな線形型の提案の裏で,副産物として Local Do という拡張が提案されている.今回は,その拡張の紹介と最近思ってることのお話.</p>
<div class="section" id="auto-id-3">
<h2>Local Do 拡張<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Haskell の do 構文は,ご存知の通りモナドのメソッドを使った式を手続き型ライクに書ける構文だ:</p>
<img alt="do 構文の要素" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/07/local-do-and-first-type-class/local-do-and-first-type-class/do-notation-syntax.png"/>
<p>この構文は次の <tt class="docutils literal">Prelude</tt> にある定義を想定している <a class="footnote-reference" href="#monad-class-in-ghc" id="auto-id-4">[1]</a>:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">Applicative</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o">>>=</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">MonadFail</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">fail</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">String</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span>
<span class="p">(</span><span class="o">>></span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Applicative</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">b</span>
<span class="p">(</span><span class="o">>></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="o">*></span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>こいつらを元に,次の変換を行う:</p>
<img alt="do 構文の脱糖変換" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/07/local-do-and-first-type-class/local-do-and-first-type-class/do-notation-translation.png"/>
<p>この構文は <tt class="docutils literal">Monad</tt> クラス専用だが,現在 Haskell には,</p>
<ul class="simple">
<li><a class="reference external" href="http://hackage.haskell.org/package/indexed-0.1.3/docs/Control-Monad-Indexed.html#t:IxMonad">IxMonad</a> : indexed monad</li>
<li><a class="reference external" href="https://hackage.haskell.org/package/effect-monad-0.8.1.0/docs/Control-Effect.html#t:Effect">Effect</a> : graded monad</li>
<li><a class="reference external" href="https://hackage.haskell.org/package/rmonad-0.8.0.2/docs/Control-RMonad.html#t:RMonad">RMonad</a> : 制約付き monad</li>
</ul>
<p>やそれを一般化した <a class="reference external" href="https://hackage.haskell.org/package/supermonad">super monad</a> などがあり,これらは全て型の異なる <tt class="docutils literal"><span class="pre">(>>=)</span></tt> / <tt class="docutils literal">fail</tt> / <tt class="docutils literal"><span class="pre">(>>)</span></tt> を持つ.また, <a class="reference external" href="https://github.com/tweag/linear-base/blob/0d6165fbd8ad84dd1574a36071f00a6137351637/src/Control/Monad/Linear.hs#L43">線形型用の monad</a> なども考案されている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">Applicative</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o">>>=</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="p">(</span><span class="o">>></span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">MonadFail</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">fail</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">String</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span>
</pre></div></td></tr></table></div>
<p>これらは型は違うものの同じようなメソッドを持っており,同じように do 構文が適用できる.実際, indexed monad については, <a class="reference external" href="http://hackage.haskell.org/package/indexed-do-notation">indexed-do-notation</a> というパッケージで <tt class="docutils literal">TemplateHaskell</tt> によっての実装が提供されている.また,線形型用の monad を提供する <tt class="docutils literal"><span class="pre">linear-base</span></tt> パッケージには, <tt class="docutils literal">Control.Monad.Linear.Builder</tt> というモジュールが提供されており,その中では次のデータ構造が提供されている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Control.Monad.Linear</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">Linear</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">BuilderType</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Builder</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="o">>>=</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="o">>></span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">fail</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="kt">MonadFail</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">String</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">return</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">->.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">monadBuilder</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">BuilderType</span>
<span class="nf">monadBuilder</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Builder</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="o">>>=</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="kt">Linear</span><span class="o">.>>=</span><span class="p">)</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="o">>></span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="kt">Linear</span><span class="o">.>></span><span class="p">)</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">fail</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="n">fail</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">return</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="n">return</span>
<span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">Control.Monad.Linear</tt> は線形型用の monad を提供するモジュールだ.この <tt class="docutils literal">Builder</tt> と <tt class="docutils literal">RebindableSyntax</tt> / <tt class="docutils literal">RecordWildCards</tt> 拡張を組み合わせて,以下のようなコードが書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE BlockArguments #-}</span>
<span class="cm">{-# LANGUAGE OverloadedStrings #-}</span>
<span class="cm">{-# LANGUAGE RebindableSyntax #-}</span>
<span class="cm">{-# LANGUAGE RecordWildCards #-}</span>
<span class="kr">module</span><span class="w"> </span><span class="nn">Main</span><span class="w"> </span><span class="kr">where</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Prelude</span><span class="w"> </span><span class="k">hiding</span><span class="w"> </span><span class="p">(</span><span class="kt">Monad</span><span class="p">(</span><span class="o">..</span><span class="p">),</span><span class="w"> </span><span class="kt">MonadFail</span><span class="p">(</span><span class="o">..</span><span class="p">))</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Prelude.Linear</span><span class="w"> </span><span class="p">(</span><span class="kt">Unrestricted</span><span class="p">(</span><span class="o">..</span><span class="p">))</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Control.Monad.Linear.Builder</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">Linear</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">System.IO</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">System</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">System.IO.Resource</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">RIO</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Data.String</span><span class="w"> </span><span class="p">(</span><span class="nf">fromString</span><span class="p">)</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">run</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">writeSomething</span><span class="w"> </span><span class="s">"something.txt"</span>
<span class="nf">writeSomething</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">FilePath</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="kt">RIO</span><span class="w"> </span><span class="p">(</span><span class="kt">Unrestricted</span><span class="w"> </span><span class="nb">()</span><span class="p">)</span>
<span class="nf">writeSomething</span><span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">h0</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">openFile</span><span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="kt">System</span><span class="o">.</span><span class="kt">WriteMode</span>
<span class="w"> </span><span class="n">h1</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">hPutStr</span><span class="w"> </span><span class="n">h0</span><span class="w"> </span><span class="s">"some"</span>
<span class="w"> </span><span class="n">h2</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">hPutStr</span><span class="w"> </span><span class="n">h1</span><span class="w"> </span><span class="s">"thing"</span>
<span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">hClose</span><span class="w"> </span><span class="n">h2</span>
<span class="w"> </span><span class="n">return</span><span class="w"> </span><span class="p">(</span><span class="kt">Unrestricted</span><span class="w"> </span><span class="nb">()</span><span class="p">)</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="kt">Builder</span><span class="p">{</span><span class="o">..</span><span class="p">}</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="n">monadBuilder</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">RebindableSyntax</tt> は整数リテラルや do 構文などの糖衣構文において,中で使われるメソッドを, <tt class="docutils literal">Prelude</tt> から探す代わりに現在のスコープから探すようにする拡張だ.なので,今回は通常の <tt class="docutils literal">Monad</tt> のメソッドの代わりに, <tt class="docutils literal"><span class="pre">Linear.Builder{..}</span> = Linear.monadBuilder</tt> で束縛したものが do 構文で使われる事になる.</p>
<p><tt class="docutils literal">TemplateHaskell</tt> を使った例はコンパイル速度の問題と依存関係の問題がある. <tt class="docutils literal">RebindableSyntax</tt> は <tt class="docutils literal">NoImplicitPrelude</tt> に依存する他, do 構文以外の様々な構文に影響するという問題がある.そこで do 構文のみで内部で使用するメソッドを切り替えられるようにする拡張が, <tt class="docutils literal">LocalDo</tt> 拡張になる.</p>
<p>現在の提案では, do 構文を拡張し,次のようなことが指定できるようにするという事になっている:</p>
<pre class="literal-block">
do @Linear.monadBuilder
h0 <- RIO.openFile path System.WriteMode
h1 <- RIO.hPutStr h0 "some"
h2 <- RIO.hPutStr h1 "thing"
RIO.hClose h2
return (Unrestricted ())
</pre>
<p>こう書くと,脱糖の際 <tt class="docutils literal">Linear.monadBuilder</tt> のフィールドを使うようになる.</p>
</div>
<div class="section" id="auto-id-5">
<h2>現在の提案の問題点<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ところで,単純に脱糖の際 <tt class="docutils literal">Linear.monadBuilder</tt> のフィールドを使うと言ったが,実際は幾つかのデザイン選択がある.例えば,次のプログラムを見てみよう:</p>
<pre class="literal-block">
do @Linear.monadBuilder
x <- m1 >> m2
pure x
</pre>
<p>このプログラムはどう翻訳されるべきだろうか? 例えば次の変換があり得るだろう:</p>
<pre class="literal-block">
let
Linear.Builder{..} = Linear.monadBuilder
in (m1 >> m2) >>= \x -> pure x
</pre>
<p>このプログラムへの変換は,あなたが想定していたものだろうか? この例では, do 構文中に出てきた <tt class="docutils literal">>></tt> も線形型版に置き換わる.これは一見便利だが,多くの場合意図しない挙動であり,しかもプログラム片を別の関数に切り出した場合動作が異なってしまう.これは言語デザインの一貫性の面からも微妙だ.現状の提案では,脱糖は実は Haskell の構文に則っておらず,上のような名前の衝突も起こすようなものになっている:</p>
<pre class="literal-block">
do @b { x <- u; stmts } = case b of { >>= } -> (>>=) u $ \x -> do @b { stmts }
do @b { u; stmts } = case b of { >> } -> (>>) u $ do @b { stmts }
</pre>
<p><tt class="docutils literal">NameFieldPuns</tt> を前提に書かれてると提案では述べているが,実際にはこの拡張を有効にしても右側の構文はコンパイルが通らない.コンストラクタが省略されているためだ.読み方としては,単一コンストラクタのフィールドを束縛するのが,擬似構文 <tt class="docutils literal">case v of { field } <span class="pre">-></span> e</tt> ということになる.現在の提案は,これが問題視されているが,一意な解決案が出ていない.</p>
<p>解決案の一つとして, <tt class="docutils literal">LocalDo</tt> のための以下のような <tt class="docutils literal">Builder</tt> 型を作るという提案がなされている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">Builder</span><span class="w"> </span><span class="n">t_bind</span><span class="w"> </span><span class="n">t_then</span><span class="w"> </span><span class="n">t_fail</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Builder</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">(</span><span class="o">>>=</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">t_bind</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="o">>></span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">t_then</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">fail</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">t_fail</span>
<span class="w"> </span><span class="p">}</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Builder</span>
<span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
<span class="w"> </span><span class="p">(</span><span class="n">forall</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="w"> </span><span class="kt">MonadFail</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">String</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="nf">monadBuilder</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">MonadBuilder</span>
<span class="nf">monadBuilder</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Builder</span><span class="w"> </span><span class="p">(</span><span class="kt">Prelude</span><span class="o">.>>=</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Prelude</span><span class="o">.>></span><span class="p">)</span><span class="w"> </span><span class="kt">Prelude</span><span class="o">.</span><span class="n">fail</span>
</pre></div></td></tr></table></div>
<p>後は脱糖で使う関数を <tt class="docutils literal">Builder</tt> のフィールドにすればいい.個人的にはこの提案が落とし所だと思う.一応触れられてる問題点としては,新たにフィールドを追加すると既存のコードが壊れやすいということだ.そのため,次のような形にすることも提案されている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">HasBind</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="kt">TypeOfBind</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="o">*</span>
<span class="w"> </span><span class="n">localBind</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TypeOfBind</span><span class="w"> </span><span class="n">b</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">HasThen</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="kt">TypeOfThen</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="o">*</span>
<span class="w"> </span><span class="n">localThen</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">TypeOfThen</span><span class="w"> </span><span class="n">b</span>
<span class="o">...</span>
<span class="kr">data</span><span class="w"> </span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MonadBuilder</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">HasBind</span><span class="w"> </span><span class="p">(</span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="kt">TypeOfBind</span><span class="w"> </span><span class="p">(</span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="n">localBind</span><span class="w"> </span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="o">>>=</span><span class="p">)</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">HasThen</span><span class="w"> </span><span class="p">(</span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="kt">TypeOfBind</span><span class="w"> </span><span class="p">(</span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
<span class="w"> </span><span class="n">localBind</span><span class="w"> </span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="o">>></span><span class="p">)</span>
<span class="o">...</span>
</pre></div></td></tr></table></div>
<p>この場合,フィールドが増えても既存のコードを壊さないで拡張できるメリットがある.ただここまでくると,実は同じ機能を持ってる型クラス既にあるじゃんということで,次のようにすることが現在提案されている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Type</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">Type</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">MonadBuilder</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">TypeOfMonadBind</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">HasField</span><span class="w"> </span><span class="s">">>="</span><span class="w"> </span><span class="p">(</span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">TypeOfMonadBind</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">getField</span><span class="w"> </span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="o">>>=</span><span class="p">)</span>
<span class="kr">type</span><span class="w"> </span><span class="kt">TypeOfMonadThen</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">HasThen</span><span class="w"> </span><span class="p">(</span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">TypeOfMonadThen</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">getField</span><span class="w"> </span><span class="kt">MonadBuilder</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="o">>></span><span class="p">)</span>
<span class="o">...</span>
</pre></div></td></tr></table></div>
<p>なお PureScript の方には,実は <tt class="docutils literal">LocalDo</tt> 相当の機能が既に入っている. PureScript では qualified do と呼ばれていて,以下のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="nn">Prelude</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">P</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Effect</span><span class="w"> </span><span class="p">(</span><span class="kt">Effect</span><span class="p">)</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Effect.Console</span><span class="w"> </span><span class="p">(</span><span class="nf">log</span><span class="p">)</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Effect</span><span class="w"> </span><span class="kt">Unit</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">P</span><span class="o">.</span><span class="kr">do</span>
<span class="w"> </span><span class="n">log</span><span class="w"> </span><span class="s">"Hello"</span>
<span class="w"> </span><span class="n">log</span><span class="w"> </span><span class="s">"World!"</span>
</pre></div></td></tr></table></div>
<p>qualified do はモジュールを指定して,そのモジュールの中から脱糖に必要な関数を探してくる.モジュールを切り替えることで DSL を様々なモジュールに着地させることができるわけだ.この方式でも名前空間の破壊は起こらないため,解決策の一つとして提案されている.ただ,これは実行時に着地先を変えることは出来ないため,表現能力が下がってしまう点が問題視されている.</p>
<p>また型解決についてあまり触れられていないのも,問題視されている.最悪脱糖してから型検査すればいいと思うが,かなりエラーメッセージが不親切になるだろう.また,脱糖してからだと,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">do</span><span class="w"> </span><span class="o">@</span><span class="n">builder</span>
<span class="w"> </span><span class="n">putStr</span><span class="w"> </span><span class="s">"Hello "</span>
<span class="w"> </span><span class="n">putStr</span><span class="w"> </span><span class="s">"World!"</span>
</pre></div></td></tr></table></div>
<p>と</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">do</span><span class="w"> </span><span class="o">@</span><span class="n">builder</span>
<span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">putStr</span><span class="w"> </span><span class="s">"Hello "</span>
<span class="w"> </span><span class="n">putStr</span><span class="w"> </span><span class="s">"World!"</span>
</pre></div></td></tr></table></div>
<p>で前者は <tt class="docutils literal"><span class="pre">(>>)</span></tt> だけ,後者は <tt class="docutils literal"><span class="pre">(>>=)</span></tt> だけを使うということになるが,片方は型エラーでもう片方はコンパイルに通るといったことになり,一貫性がない.そもそも, <tt class="docutils literal">builder</tt> が全てのフィールドを兼ね揃えているかチェックすべきかどうかという点もある.また, <tt class="docutils literal">builder</tt> の型をどう推論するか, <tt class="docutils literal">LocalDo</tt> の文の型推論はどうするかについても考える必要があるだろう.</p>
<p>このように現状結構穴がある提案になっていて,提案者に対し修正が要求されている.また,積極的な議論が呼びかけられている.何かアイデアや疑問があれば,投げておくといいかもしれない.</p>
</div>
<div class="section" id="haskell">
<h2>Haskell の型クラスについて思うこと<a class="headerlink" href="#haskell" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ところで少し話が変わるが, Haskell の型クラスは内部では単なるデータ型に変換される.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">class</span><span class="w"> </span><span class="kt">SampleC</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">sampleM1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="n">sampleM2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">SampleC</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">sampleM1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="n">sampleM2</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="nf">sampleV</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">SampleC</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span>
<span class="nf">sampleV</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sampleM2</span><span class="w"> </span><span class="n">sampleM1</span>
<span class="nf">sampleV2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sampleV2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sampleV</span>
</pre></div></td></tr></table></div>
<p>みたいなコードがあった場合,内部的には</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">DSampleC</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DSampleC</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">sampleM1</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">sampleM2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">dSampleC_Int</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">DSampleC</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">dSampleC_Int</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">DSampleC</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">sampleM1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">0</span>
<span class="w"> </span><span class="p">,</span><span class="w"> </span><span class="n">sampleM2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="p">}</span>
<span class="nf">sampleV</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">DSampleC</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">sampleV</span><span class="w"> </span><span class="kt">DSampleC</span><span class="p">{</span><span class="o">..</span><span class="p">}</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sampleM2</span><span class="w"> </span><span class="n">sampleM1</span>
<span class="nf">sampleV2</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">sampleV2</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">sampleV</span><span class="w"> </span><span class="n">dSampleC_Int</span>
</pre></div></td></tr></table></div>
<p>みたいなコードが生成される.型クラス相当の内部で定義されているデータ型を辞書と呼び,型クラスの制約が実際には辞書を渡していく形式に変換されることから,この変換を辞書渡しスタイルと呼ぶことがある.ところで,このように見てみると型クラスの仕組みとは,実際には辞書という暗黙のオブジェクトをパラメータとして持つ関数を定義する仕組みであるように見えてくる.そしてパラメータはコンパイル時にインスタンス解析によって暗黙的に埋め込まれる.今回の <tt class="docutils literal">Builder</tt> 型は,実際には内部の辞書を顕在化させているにすぎないように見えてくる.もちろん,明示的にデータ型を指定できるので動的に作ったオブジェクトを指定することもできるわけだが,ほとんどの場合辞書を一回 Haskell で扱えるデータ型に変換して渡すことになるだろう.これは二重に手間だ.</p>
<p>Haskell の型クラスの実装を悪用した有名なパッケージとして, <a class="reference external" href="https://hackage.haskell.org/package/reflection">reflection</a> というものがある.これは一つしかメソッドを持たない型クラスが,内部で <tt class="docutils literal">newtype</tt> 相当の実装をすることを利用し,暗黙の引数を型クラスの仕組みを通して実現するパッケージだ.これは,暗黙の引数以上のことを実現でき,辞書を一旦顕在化させてその後また型制約に戻すといったテクニックに利用できる.ただ,こちらも本来なら辞書をそのまま利用できれば解決できる話だ.</p>
<p>つまり Haskell の型クラスインスタンスが第1級でなく,そのためいくつかの場面で不便だということだ.もし第1級であれば,今回の提案ももう少し工夫の余地があっただろう. Scala はこれを実現していて,単に暗黙の引数として Scala のなんていうことはないクラスのインスタンスが渡されるので,それを通常の Scala プログラミングの範囲で取り扱える.同じように単に暗黙の引数とその解決のためのオブジェクトを簡潔に定義できる糖衣構文さえあれば,実は型クラスの仕組みは実現できる. Haskell の型クラスはかなり古参なので,いまさら変えようということになってもちょっと難しいと思うが,最近ちょっとそこら辺が不満で,今回の提案が入ってビルダを書く羽目になるたび,そういうこと考えるんだろなあというぼやきでした.</p>
<p>なお,こういうことを考えてる人は昔からちらほらいて,最近もそういう記事を目にした.まあ,みんなそう思うよねというお話でした.</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>なんか最後ぐだぐだになったが, <tt class="docutils literal">LocalDo</tt> 拡張の提案とその問題点,現在の議論の内容を紹介した.それから,型クラスについてちょっと不満に思っていることを書いた.</p>
<p>個人的にはこういう系は F# のコンピュテーション式が一番使い勝手良いなあと思っていたので,それ相当のことができる機能が GHC 拡張で提案されてるのは嬉しい.ただ,現状お蔵入りしかけなので,議論が活発になればいいなということで書いた.</p>
<p>後この記事は <a class="reference external" href="https://haskell-jp.connpass.com/event/138061/">Haskell-jpもくもく会</a> の時間を使って書いたので宣伝をしとくと,月一ぐらいで Haskell に関していろんな人が集まって,1日個々で作業し成果を発表する会があって, Haskell-jp さんが主催してる.分からないことがあればすぐ隣の人とかに聞けるので,興味があれば参加してみるといいのではないでしょうか.</p>
<p>ということで,今日はこれで.</p>
<table class="docutils footnote" frame="void" id="monad-class-in-ghc" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[1]</a></td><td>GHC では <tt class="docutils literal">Monad</tt> は, <tt class="docutils literal">GHC.Base</tt> モジュールで定義されている.現状の GHC 8.6 ではこの記事で述べたものの他に <tt class="docutils literal">return</tt> / <tt class="docutils literal"><span class="pre">(>>)</span></tt> / <tt class="docutils literal">fail</tt> メソッドがある.これは, <a class="reference external" href="https://prime.haskell.org/wiki/Libraries/Proposals/MonadFail">MFP</a> / <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/wikis/proposal/monad-of-no-return">MRP</a> で削除される予定.この記事では, MFP / MRP が最終段階までいったことを想定した定義を書いている.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/07/local-do-and-first-type-class.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/07/local-do-and-first-type-class.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Call Arity と融合変換2019-07-26T13:54:20+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-07-26:/blog/posts/2019/07/call-arity-and-oneshot/<p>GHC は,最適化のため Call Arity と呼ばれるコード解析を行っている.この解析で,自由変数が何個引数を持っていいかを判定 …</p><p>GHC は,最適化のため Call Arity と呼ばれるコード解析を行っている.この解析で,自由変数が何個引数を持っていいかを判定し,イータ展開を可能にする.リストにおける融合変換とも密接な関係のある解析だ.こいつの存在とどういうことをやっているかはだいたい知っていたんだけど,ちょっと詳しく知りたい事例があったので調べてみた.そのメモ.</p>
<p>なお元ネタは,Breitner (nomeata) 先生の <a class="reference external" href="https://www.sciencedirect.com/science/article/pii/S1477842416300756">Call Arity</a> .</p>
<div class="section" id="auto-id-2">
<h2>イータ展開と最適化<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Haskell は知っての通り関数型プログラミング言語なので,息を吐くように関数を第1級として使うし,標準ライブラリに無数の高階関数がある.関数は全てカリー化されていて,部分適用も可能だ.ただ困ったことに Haskell は実用されており,これらの関数型プログラミング言語で常用されているテクニックで書かれたプログラムで,通常のプログラミング言語程度と妥当な勝負ができるぐらいのパフォーマンスを出さなければならない.しかし,カリー化と部分適用が気軽にできることは,実行マシンを考えると,かなりのハンデになる.</p>
<p>次のプログラムを例に考えてみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">let</span>
<span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span>
<span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="mi">1</span>
<span class="kr">in</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">2</span>
</pre></div></td></tr></table></div>
<p>このプログラムが何の変換もなされず,直接実行マシンに入力されるとする.単純に考えると全ての関数は一引数であると思って,関数適用を見つけたら引数を一つ一つ適用していけば実行できるわけだが,例えば今回の <tt class="docutils literal">g</tt> のような多引数受け取らないと結果が返せない関数は単純に引数をキャプチャしたクロージャを生成するだけであり,かなり非効率になる.さすがに GHC ではそこまで安直なことはやっていなくて,一度に多引数の適用ができる場合中間オブジェクトを生成せずに関数適用を行う.現在の GHC では, eval/apply 方式と呼ばれる実行戦略を取っていて,関数の定義の形を見て引数の数が足りなければ部分適用を表す中間オブジェクトを生成し,引数の数が足りた時点で簡約を行う.今回の場合,大雑把には,</p>
<ol class="arabic simple">
<li><tt class="docutils literal">f 2</tt> を評価しようとする.</li>
<li><tt class="docutils literal">f</tt> は <tt class="docutils literal">g 1</tt> を表すサンクとなっているので,引数の <tt class="docutils literal">2</tt> をスタックに退避させて, <tt class="docutils literal">f</tt> をまず評価する.</li>
<li><tt class="docutils literal">g</tt> は 2 引数関数なので, <tt class="docutils literal">1</tt> だけでは足りないので,部分適用 <tt class="docutils literal">g 1</tt> を表す中間オブジェクトを生成し, <tt class="docutils literal">f</tt> に再束縛する.</li>
<li><tt class="docutils literal">f</tt> に退避した <tt class="docutils literal">2</tt> を適用すると,部分適用でキャプチャした <tt class="docutils literal">1</tt> と合わせて引数が足りるので,その簡約結果 <tt class="docutils literal">1 + 2</tt> を返す.</li>
</ol>
<p>のような動作をする.つまり,上のコードは中間オブジェクトを生成するため,その分のオーバーヘッドがかかる.ただこのようなコードは, Haskeller にとっては日常茶飯事であるわけなので,できるだけオーバーヘッドは無くしたいわけだ.実は,次のように少しコードを書き直すと,中間オブジェクトを生成する必要がなくなる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">let</span>
<span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span>
<span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="n">x</span>
<span class="kr">in</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">2</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">f</tt> の定義に引数を一つ足しただけだ.この場合,</p>
<ol class="arabic simple">
<li><tt class="docutils literal">f 2</tt> を評価しようとする.</li>
<li><tt class="docutils literal">f</tt> は 1 引数関数なので,引数の <tt class="docutils literal">2</tt> をそのまま適用する.</li>
<li>適用した結果の <tt class="docutils literal">g 1 2</tt> において, <tt class="docutils literal">g</tt> は 2 引数関数なので,引数 <tt class="docutils literal">1</tt> , <tt class="docutils literal">2</tt> をそのまま適用する.</li>
<li>簡約結果 <tt class="docutils literal">1 + 2</tt> を返す.</li>
</ol>
<p>となる.一般に関数を表す式 <tt class="docutils literal">f</tt> について, <tt class="docutils literal">\x <span class="pre">-></span> f x</tt> というようにラムダ抽象で包む形に変換する操作をイータ展開 (eta expansion) と呼び,今回は元のコードの <tt class="docutils literal">f</tt> をイータ展開している.このようにイータ展開を行うことで,部分適用のための中間オブジェクト生成を抑制できる場合がある.</p>
<p>イータ展開は他にも,情報を付加することで <tt class="docutils literal">let</tt> や ラムダ抽象のフローティング変換補助を行うことができたり,結構最適化の際に嬉しい.ただ,なんでもかんでもイータ展開すればいいかというとそうでもない.具体的には次のようなケース:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">let</span>
<span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span>
<span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">expensiveExpression</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="mi">0</span>
<span class="kr">in</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="mi">3</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">expensiveExpression</tt> は評価に時間のかかる式が入るとする.この場合, <tt class="docutils literal">f</tt> をイータ展開すると, <tt class="docutils literal">f 2</tt> , <tt class="docutils literal">f 3</tt> それぞれの呼び出しで <tt class="docutils literal">expensiveExpression</tt> が計算されることになる.それに対し,イータ展開しない場合,サンクが評価された後2回目では計算が起こらない.</p>
<p>以上のようなことを考慮し,イータ展開していい引数の数を解析する手法が Call Arity 解析になる.</p>
</div>
<div class="section" id="auto-id-3">
<h2>Call Arity 解析<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Call Arity 解析が入る前も, GHC では似たような解析をしていてこれは Arity 解析と呼ばれていた. Call Arity 解析は従来の Arity 解析を Co-Call 解析と呼ばれる解析情報によって補助することで,より精度を上げようというものっぽい.具体的には以下のようなことを考える.</p>
<p>対象の構文として以下のものを考える.</p>
<img alt="通常のラムダ計算の項に加えて,条件分岐, letrec とかを入れてる" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/07/call-arity-and-oneshot/call-arity-and-oneshot/target-syntax.png"/>
<p>今回の解析には型情報は必要ないので,考えるのは Core から型情報を抜いたようなもの.ただ, case とかはややこしい上にあまり本質ではないので,代わりに条件分岐を入れている. case の解析は条件分岐と同じことをすればいい.これに対し,変数集合を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>V</mi></mrow><annotation encoding="application/x-tex">V</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span></span> ,式の集合を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi></mrow><annotation encoding="application/x-tex">E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> として二つの相互に依存する解析関数</p>
<ul class="simple">
<li>Arity 解析: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi>n</mi></msub><mo>:</mo><mi>E</mi><mo>→</mo><mo stretchy="false">(</mo><mi>V</mi><mo>⇀</mo><mi mathvariant="double-struck">N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">A_n: E \to (V \rightharpoonup \mathbb{N})</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇀</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathbb">N</span><span class="mclose">)</span></span></span></span></span></li>
<li>Co-Call 解析: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mi>n</mi></msub><mo>:</mo><mi>E</mi><mo>→</mo><mi mathvariant="script">G</mi><mo stretchy="false">(</mo><mi>V</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">C_n: E \to \mathcal{G}(V)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal" style="margin-right:0.0593em;">G</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>を考える. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⇀</mo></mrow><annotation encoding="application/x-tex">\rightharpoonup</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">⇀</span></span></span></span></span> は部分関数, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="script">G</mi><mo stretchy="false">(</mo><mi>V</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathcal{G}(V)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal" style="margin-right:0.0593em;">G</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mclose">)</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>V</mi></mrow><annotation encoding="application/x-tex">V</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span></span> を頂点とする無向グラフを表す. Arity 解析 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">A_n(e)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span></span></span></span></span> は受け取った式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> に対して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> 個引数が適用されたと仮定し,中の変数のアリティを解析した上でその対応表を返す. Co-Call 解析 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">C_n(e)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span></span></span></span></span> は受け取った式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> に対して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> 個引数が適用されたと仮定し,中の変数で同時に実行されるパスがある場合,辺が追加されたグラフを返す.なお自身への辺も許容され,辺がある場合2度以上使用される場合がある.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">let</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="kr">in</span>
<span class="kr">let</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="kr">in</span>
<span class="nf">f</span><span class="w"> </span><span class="n">z</span>
</pre></div></td></tr></table></div>
<p>というプログラム <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> があった時,これを <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">A_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> にかけると,結果は次のようになる:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mn>0</mn></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">{</mo><mi mathvariant="monospace">f</mi><mo>↦</mo><mn>1</mn><mo separator="true">,</mo><mi mathvariant="monospace">z</mi><mo>↦</mo><mn>0</mn><mo separator="true">,</mo><mi mathvariant="monospace">s</mi><mo>↦</mo><mn>0</mn><mo separator="true">,</mo><mi mathvariant="monospace">t</mi><mo>↦</mo><mn>0</mn><mo separator="true">,</mo><mi mathvariant="monospace">g</mi><mo>↦</mo><mn>2</mn><mo separator="true">,</mo><mi mathvariant="monospace">p</mi><mo>↦</mo><mn>2</mn><mo separator="true">,</mo><mi mathvariant="monospace">x</mi><mo>↦</mo><mn>0</mn><mo separator="true">,</mo><mi mathvariant="monospace">y</mi><mo>↦</mo><mn>0</mn><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">
A_0(e) = \{
\mathtt{f} \mapsto 1,
\mathtt{z} \mapsto 0,
\mathtt{s} \mapsto 0,
\mathtt{t} \mapsto 0,
\mathtt{g} \mapsto 2,
\mathtt{p} \mapsto 2,
\mathtt{x} \mapsto 0,
\mathtt{y} \mapsto 0
\}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathtt">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathtt">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathtt">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathtt">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8667em;vertical-align:-0.2222em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathtt">g</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8667em;vertical-align:-0.2222em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathtt">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathtt">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8667em;vertical-align:-0.2222em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathtt">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mclose">}</span></span></span></span></span></div>
<p>また, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mn>0</mn></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">C_0(e)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span></span></span></span></span> は以下のグラフを返す:</p>
<img alt="それぞれの変数が両方計算されるパスを表すグラフ" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/07/call-arity-and-oneshot/call-arity-and-oneshot/example-co-call-graph.png"/>
<p><tt class="docutils literal">s</tt> が真の場合は <tt class="docutils literal">f</tt> の中の条件分岐で <tt class="docutils literal">g s</tt> の方に入り 2 回目が呼ばれることになるので,自身へのループを持つ.それ以外の変数は 1 回しか使用されない.この自身へのループを持つかは重要で,これがある場合イータ展開すると本来サンク一回の評価で良かったものを複数回評価してしまうことになる.また <tt class="docutils literal">g</tt> や <tt class="docutils literal">f</tt> の内部の変数は,それぞれの関数が呼ばれると使用されるので, <tt class="docutils literal">g</tt> や <tt class="docutils literal">f</tt> に紐づく変数と紐づくことになる.イメージとしてはこんな感じ.</p>
<p>解析は再帰的に定義される.詳細は論文の方にまとまってるので,そちらを参照してくれって感じ.一応,条件分岐とラムダ抽象, let だけ紹介しておく.</p>
<dl class="docutils">
<dt>条件分岐</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mo>=</mo><mo><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">f</mi></mrow></mo><msub><mi>e</mi><mn>1</mn></msub><mo><mrow><mi mathvariant="bold">t</mi><mi mathvariant="bold">h</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">n</mi></mrow></mo><msub><mi>e</mi><mn>2</mn></msub><mo><mrow><mi mathvariant="bold">e</mi><mi mathvariant="bold">l</mi><mi mathvariant="bold">s</mi><mi mathvariant="bold">e</mi></mrow></mo><msub><mi>e</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">
e = \mathop{\mathbf{if}} e_1 \mathop{\mathbf{then}} e_2 \mathop{\mathbf{else}} e_3
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mop"><span class="mord"><span class="mord mathbf" style="margin-right:0.10903em;">if</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">then</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">else</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></div>
<p>について,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>A</mi><mn>0</mn></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>⊔</mo><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>⊔</mo><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>3</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
A_n(e) = A_0(e_1) \sqcup A_n(e_2) \sqcup A_n(e_3)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>C</mi><mn>0</mn></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>∪</mo><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>∪</mo><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>3</mn></msub><mo stretchy="false">)</mo><mo>∪</mo><mo stretchy="false">(</mo><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>×</mo><mo stretchy="false">(</mo><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>∪</mo><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>3</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
C_n(e) = C_0(e_1) \cup C_n(e_2) \cup C_n(e_3) \cup (\mathit{fv}(e_1) \times (\mathit{fv}(e_2) \cup \mathit{fv}(e_3)))
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)))</span></span></span></span></span></div>
<p>と定義する.ここで, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathit{fv}(e)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> の中の自由変数の集合,他の演算子は以下のようになる:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>X</mi><mn>1</mn></msub><mo>⊔</mo><msub><mi>X</mi><mn>2</mn></msub><mo>=</mo><mo stretchy="false">{</mo><mi>x</mi><mo>↦</mo><msub><mi>n</mi><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">n</mi></mrow></msub><mo>∣</mo><mi>x</mi><mo>∈</mo><mrow><mi mathvariant="normal">d</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mo stretchy="false">(</mo><msub><mi>X</mi><mn>1</mn></msub><mo>∪</mo><msub><mi>X</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo separator="true">,</mo><msub><mi>n</mi><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">i</mi><mi mathvariant="normal">n</mi></mrow></msub><mo>=</mo><mi>min</mi><mo></mo><mo stretchy="false">{</mo><mi>n</mi><mo>∣</mo><mi>x</mi><mo>↦</mo><mi>n</mi><mo>∈</mo><msub><mi>X</mi><mn>1</mn></msub><mo>∪</mo><msub><mi>X</mi><mn>2</mn></msub><mo stretchy="false">}</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">
X_1 \sqcup X_2 = \{x \mapsto n_{\mathrm{min}} \mid x \in \mathrm{dom}(X_1 \cup X_2), n_{\mathrm{min}} = \min \{n \mid x \mapsto n \in X_1 \cup X_2\}\}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3175em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">min</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">dom</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3175em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">min</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">{</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.522em;vertical-align:-0.011em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}}</span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>V</mi><mn>1</mn></msub><mo>×</mo><msub><mi>V</mi><mn>2</mn></msub><mo>=</mo><mo stretchy="false">{</mo><msub><mi>v</mi><mn>1</mn></msub><mo><mtext>–</mtext></mo><msub><mi>v</mi><mn>2</mn></msub><mo>∣</mo><msub><mi>v</mi><mn>1</mn></msub><mo>∈</mo><msub><mi>V</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>v</mi><mn>2</mn></msub><mo>∈</mo><msub><mi>V</mi><mn>2</mn></msub><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">
V_1 \times V_2 = \{v_1 \mathrel{\text{--}} v_2 \mid v_1 \in V_1, v_2 \in V_2\}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord">–</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span></span></div>
<p class="last">Arity 解析の方は,まず <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> に何個引数が適用されようが関係なくアリティ 0 になる. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">e_3</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> の計算結果によって, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> の引数がそのまま適用されることになる. Co-Call 解析の方は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> の結果によって <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">e_3</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> どちらかが実行されることになるので,そのどちらかの実行を表す辺を追加するだけ.</p>
</dd>
<dt>ラムダ抽象</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mo>=</mo><mtext mathvariant="monospace">\</mtext><msub><mi>x</mi><mn>1</mn></msub><mo>⋯</mo><msub><mi>x</mi><mi>m</mi></msub><mo lspace="0.22em" rspace="0.22em"><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">
e = \text{\texttt{\textbackslash}} x_1 \cdots x_m \mathbin{\text{\texttt{->}}} e_1
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord text"><span class="mord text"><span class="mord texttt">\</span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord text"><span class="mord text"><span class="mord texttt">-></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></div>
<p>について,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>A</mi><msup><mi>n</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>=</mo><msup><mi>n</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>+</mo><mi>m</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>A</mi><mn>0</mn></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo><</mo><mi>m</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
A_n(e) = \left\{\begin{array}{ll}
A_{n'}(e_1) &(n = n' + m) \\
A_0(e_1) &(n < m)
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.328em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>C</mi><msup><mi>n</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>=</mo><msup><mi>n</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>+</mo><mi>m</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>×</mo><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo><</mo><mi>m</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
C_n(e) = \left\{\begin{array}{ll}
C_{n'}(e_1) &(n = n' + m) \\
\mathit{fv}(e_1) \times \mathit{fv}(e_1) &(n < m)
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.328em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<p class="last">ラムダ抽象は引数が足りる場合その数分引数の数を差し引いて中の式を解析する.足りない場合がポイントで,この場合ラムダ抽象は返り値の部分値として使われるか他の関数の引数として使われ,その後どう使われるか分からない.そしてもちろん,複数回使用されることもあり得る.それ以上の解析はここではできない前提とし,複数回使用されることを想定して Co-Call 解析では <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で使用される変数同士を結びつけている.また Arity 解析も <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を展開しない前提で解析をしていく.</p>
</dd>
<dt>let</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mo>=</mo><mo><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow></mo><mi>x</mi><mo lspace="0.22em" rspace="0.22em"><mtext mathvariant="monospace">=</mtext></mo><msub><mi>e</mi><mn>1</mn></msub><mo><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow></mo><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">
e = \mathop{\mathbf{let}} x \mathbin{\text{\texttt{=}}} e_1 \mathop{\mathbf{in}} e_2
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">let</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord text"><span class="mord text"><span class="mord texttt">=</span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></div>
<p>について,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>A</mi><msub><mi>n</mi><mi>x</mi></msub></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>⊔</mo><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
A_n(e) = A_{n_x}(e_1) \sqcup A_n(e_2)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0001em;vertical-align:-0.2501em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2501em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><mi>e</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>C</mi><mrow><mi mathvariant="normal">r</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">s</mi></mrow></msub><mo>∪</mo><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>∪</mo><mo stretchy="false">(</mo><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>×</mo><mo stretchy="false">{</mo><mi>v</mi><mo>∣</mo><mi>v</mi><mo><mtext>–</mtext></mo><mi>x</mi><mo>∈</mo><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">}</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
C_n(e) = C_{\mathrm{rhs}} \cup C_n(e_2) \cup (\mathit{fv}(e_1) \times \{v \mid v \mathrel{\text{--}} x \in C_n(e_2)\})
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">e</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">rhs</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord">–</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)})</span></span></span></span></span></div>
<p>と定義する.ここで, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>n</mi><mi>x</mi></msub></mrow><annotation encoding="application/x-tex">n_x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mrow><mi mathvariant="normal">r</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">s</mi></mrow></msub></mrow><annotation encoding="application/x-tex">C_{\mathrm{rhs}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">rhs</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は以下のように定義する:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>n</mi><mi>x</mi></msub><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mn>0</mn></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>x</mi><mo><mtext>–</mtext></mo><mi>x</mi><mo>∈</mo><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo separator="true">,</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><msub><mi>e</mi><mn>1</mn></msub></mstyle><mtext> not in HNF</mtext></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
n_x = \left\{\begin{array}{ll}
0 &(x \mathrel{\text{--}} x \in C_n(e_2), \text{$e_1$ not in HNF}) \\
A_n(e_2)(x) &(\text{otherwise})
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord">–</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"> not in HNF</span></span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mrow><mi mathvariant="normal">r</mi><mi mathvariant="normal">h</mi><mi mathvariant="normal">s</mi></mrow></msub><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>C</mi><msub><mi>n</mi><mi>x</mi></msub></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>x</mi><mo><mtext>–</mtext></mo><mi>x</mi><mo>∉</mo><msub><mi>C</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>∨</mo><msub><mi>n</mi><mi>x</mi></msub><mo>=</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>×</mo><mrow><mi>f</mi><mi>v</mi></mrow><mo stretchy="false">(</mo><msub><mi>e</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">
C_{\mathrm{rhs}} = \left\{\begin{array}{ll}
C_{n_x}(e_1) &(x \mathrel{\text{--}} x \not\in C_n(e_2) \lor n_x = 0) \\
\mathit{fv}(e_1) \times \mathit{fv}(e_1) &(\text{otherwise})
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">rhs</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2501em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">fv</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord">–</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<p>ちょっと今までのものに比べ複雑だが,順を追って見ていく.</p>
<p>Arity 解析の方は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> のアリティを <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> から解析した結果を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>n</mi><mi>x</mi></msub></mrow><annotation encoding="application/x-tex">n_x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> として,それを元に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> の解析をした上で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> の結果とくっつける.単純には <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>n</mi><mi>x</mi></msub></mrow><annotation encoding="application/x-tex">n_x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi>n</mi></msub><mo stretchy="false">(</mo><msub><mi>e</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">A_n(e_2)(x)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></span> で得られるわけだけど,一番最初の話を思い出してもらうと, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> 中で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> が複数回計算され,しかも <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> が HNF ではない場合,イータ展開すると一回で済んだサンクの計算を複数回行ってしまうことになる.そこで, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> の Co-Call 解析の結果から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> が複数回使用されることが分かり, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> が HNF でない場合はイータ展開を抑制するためアリティを 0 にする.</p>
<p class="last">Co-Call 解析の方は,まず <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> の使用がたかだか一回の場合または <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> をイータ展開しないと決めた場合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> のアリティの元解析する.それ以外の場合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> が複数回使用されるとして <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で使用される変数同士を結びつける.それが <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mrow><mi>r</mi><mi>h</mi><mi>s</mi></mrow></msub></mrow><annotation encoding="application/x-tex">C_{\mathit{rhs}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathit mtight">rhs</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> の結果となる.後はそれと <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> の解析結果をくっつけ,さらに <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">e_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> が評価されるパスで評価される変数は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> の内部で使われてる変数,つまり <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">e_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> で評価される変数と同時に使用されるということでもあるので,その変数同士も結びつけるということをしている.</p>
</dd>
</dl>
<p>後は元論文のテーブルを参照してくれ.以上のことが分かれば,後は読めると思う.元論文だと正当性証明が課題として書いてあるが,その後 <a class="reference external" href="https://www.isa-afp.org/entries/Call_Arity.html">証明</a> もされてるっぽい.</p>
</div>
<div class="section" id="foldl-call-arity">
<h2>foldl と Call Arity<a class="headerlink" href="#foldl-call-arity" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ところで,最近の GHC では <tt class="docutils literal">foldl</tt> は <tt class="docutils literal">foldr</tt> で定義されている.これは融合変換を <tt class="docutils literal">foldl</tt> にも適用するためで,実は Call Arity 解析の搭載はこの定義が強い動機になっている.具体的にどういう定義になっているかというと,以下の通り <a class="footnote-reference" href="#ignored-oneshot" id="auto-id-5">[1]</a> :</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">foldl</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span>
<span class="nf">foldl</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">z0</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">foldr</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">z0</span>
</pre></div></td></tr></table></div>
<p>このコードだとちょっと混乱するかもだが,次のように書き直すと分かりやすいかもしれない:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">foldl</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">forall</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="o">.</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span>
<span class="nf">foldl</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">z0</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">foldr</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">z</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="n">z0</span>
</pre></div></td></tr></table></div>
<p>要は左畳み込みで返り値を作っていく代わりに,初期値を受け取って返り値を返す関数を関数合成により右畳み込みしていくだけ.で,抽象部分のアリティを明示して合成を明示しないで書くと上の定義が出てくる.ここで重要なのが,アキュムレータが関数になっている点.つまり,関数を再帰的に構築していくことになる点だ.</p>
<p>例えば <tt class="docutils literal">sum</tt> の定義は,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">sum</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Num</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">sum</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">foldl</span><span class="w"> </span><span class="p">(</span><span class="o">+</span><span class="p">)</span><span class="w"> </span><span class="mi">0</span>
</pre></div></td></tr></table></div>
<p>となる訳だけど,これは,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">sum</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">foldr</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="p">(</span><span class="n">z</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="mi">0</span>
</pre></div></td></tr></table></div>
<p>と等しくなる.これを次の生産者とくっつけたものを考えてみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">sum</span><span class="w"> </span><span class="p">(</span><span class="n">filter</span><span class="w"> </span><span class="n">even</span><span class="w"> </span><span class="p">(</span><span class="n">enumFromTo</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">10</span><span class="p">))</span>
</pre></div></td></tr></table></div>
<p>リスト内包表記で書くと,これは次のようなものと同じになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">sum</span><span class="w"> </span><span class="p">[</span><span class="n">x</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">10</span><span class="p">],</span><span class="w"> </span><span class="n">even</span><span class="w"> </span><span class="n">x</span><span class="p">]</span>
</pre></div></td></tr></table></div>
<p>それぞれの関数は <tt class="docutils literal">foldr/build</tt> の融合変換が発火するようになっていて,だいたい次のような関数に落ち着く:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">go</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Num</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">even</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="nf">\</span><span class="n">z</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="p">(</span><span class="n">z</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">fn</span>
</pre></div></td></tr></table></div>
<p>これはリストの中間データを削減してはいるものの,それに相当するクロージャを都度生成してしまうためあまりよろしくない.しかしこの場合, Call Arity 解析により,より良い形に変換できる. <tt class="docutils literal">fn</tt> のアリティを 1 に, <tt class="docutils literal">go</tt> のアリティを 2 にすることが可能なことが分かるので,以下のイータ展開を行うことができる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">go</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow">=</span>
<span class="w"> </span><span class="p">(</span><span class="kr">let</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="n">z'</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="kr">if</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">))</span><span class="w"> </span><span class="n">z'</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">even</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="nf">\</span><span class="n">z</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="p">(</span><span class="n">z</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">fn</span><span class="p">)</span><span class="w"> </span><span class="n">z</span>
</pre></div></td></tr></table></div>
<p>後はベータ変換とインライン展開により,以下の形に持っていける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">go</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="ow">=</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="n">z'</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">10</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="n">z'</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="n">z'</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="kr">if</span><span class="w"> </span><span class="n">even</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kr">then</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="p">(</span><span class="n">z</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="kr">else</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="n">z</span>
</pre></div></td></tr></table></div>
<p>もちろん <tt class="docutils literal">fn</tt> をラムダリフティングで外に出すことやインライン展開することも可能で,そうなると一切クロージャ生成を行わないコードができ,しかも単純な末尾呼び出しの形になっている.さらに,引数の <tt class="docutils literal">z</tt> に関する正格性解析により,アキュムレータを正格にぶん回すことができ,元のに比べかなりの効率化が見込める.</p>
<p>このように Call Arity 解析により,関数をアキュムレータとして持つような <tt class="docutils literal">foldr</tt> を使ったプログラムを,融合変換が発火した後にさらに改善することが可能になるケースがある.特に, <tt class="docutils literal">foldl</tt> を定義そのままで最適化をかけることができるのは大きいだろう.</p>
</div>
<div class="section" id="oneshot">
<h2>oneShot 関数<a class="headerlink" href="#oneshot" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて Call Arity 解析は, Co-Call 解析により複数回使用されるかの情報を元に Arity 解析を補助することで,うまくイータ展開すべき部分と抑制すべき部分を切り分けることができる.ただラムダ抽象の解析で見た通り,ラムダ抽象のまま残ってしまってその後関数に適用される式などは,その中身が複数回使用される前提になってしまう.</p>
<p>一応 GHC では, <tt class="docutils literal">GHC.Magic.oneShot :: a <span class="pre">-></span> a</tt> という関数が提供されていて,こいつを使うとその値が単一使用であることをコンパイラに教えることができる.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">let</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="kr">in</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>というプログラムにおいて,本来の Call Arity 解析では <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi></mrow><annotation encoding="application/x-tex">g</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span></span></span></span></span> は複数回使用だと判定されてしまうため HNF でない場合イータ展開が抑制される.しかし, <tt class="docutils literal">f</tt> が引数の関数を一回しか使わないと分かっていれば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">let</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span>
<span class="kr">in</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="n">oneShot</span><span class="w"> </span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>と書くことで <tt class="docutils literal">g</tt> のイータ展開を支援できる.この例だとあまり嬉しみが分からないが, <tt class="docutils literal">oneShot</tt> は以下のようにも使える.</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">foldl</span><span class="w"> </span><span class="n">k</span><span class="w"> </span><span class="n">z0</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">foldr</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">x</span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">oneShot</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">z</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">fn</span><span class="w"> </span><span class="p">(</span><span class="n">k</span><span class="w"> </span><span class="n">z</span><span class="w"> </span><span class="n">x</span><span class="p">)))</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">xs</span><span class="w"> </span><span class="n">z0</span>
</pre></div></td></tr></table></div>
<p>これは実際の <tt class="docutils literal">foldl</tt> の定義.注目したいのはラムダの中で <tt class="docutils literal">oneShot</tt> を書いてる点. <tt class="docutils literal">foldr</tt> に渡す関数はリストの長さ分使用されるが,その中のアキュムレータとして返す関数は,各リストの要素と前のアキュムレータに対して一度きりの使用となる.</p>
<p>実際の世界では Call Arity 解析だけでうまくいかないケースもあり, <tt class="docutils literal">foldl</tt> も生産者によっては融合変換の結果微妙な形になってしまうこともある. <tt class="docutils literal">oneShot</tt> をつけておくとその補助情報で Call Arity 解析がうまくいくようになる場合もある.なので,汎用的な関数で Call Arity 解析によるイータ展開を期待するなら <tt class="docutils literal">oneShot</tt> をつけれるところは付けておくと無難だろう.</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで, <tt class="docutils literal">foldl</tt> が <tt class="docutils literal">foldr</tt> で定義されるようになった裏で,新たに搭載された解析手法を紹介した.さらに GHC 8 系では,従来の正格性解析を強化した Demand Analysis に切り替わったり, Core に join point が入ったりと内部は大きく変わっている.なお, Demand Analysis について知ってる人は, Co-Call 解析から取れる情報が Demand Analysis と被ってることに気づくと思う.実際その部分を統一化する話もあって, <a class="reference external" href="https://icfp17.sigplan.org/details/hiw-2017/14/Demand-Analysis-vs-Call-Arity">https://icfp17.sigplan.org/details/hiw-2017/14/Demand-Analysis-vs-Call-Arity</a> でそれについて触れられてるんだけど,この話が結局どうなったのか知らない.将来的にこれも取り入れられたりするんだろうか?</p>
<p>ただ Call Arity は実際うまく入らない場合もあり, <tt class="docutils literal">oneShot</tt> のような補助情報を別途つける必要も生じる.ここから <tt class="docutils literal">foldl</tt> で書けるなら明示的にループを書くよりこいつらを使った方が,より効率よくなる場合が多いということだ.これは <tt class="docutils literal">foldl'</tt> でも同じなので,正格性解析が入るかどうかを気にしたくないなら <tt class="docutils literal">foldl'</tt> を使っていれば融合変換が入り,インライン展開後もうまくワンショットラムダでぶん回す再帰に変換されるようになる.</p>
<p>あんまり詳しくなかった解析なので,これでちょっとは融合変換のパフォーマンス予測がしやすくなったんだろうか.正直融合変換周り,元のコードから形が変わりすぎて Core 出力読めねえんだよなあ.こちらからは以上です.</p>
<table class="docutils footnote" frame="void" id="ignored-oneshot" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[1]</a></td><td>実際には <tt class="docutils literal">oneShot</tt> 関数が使われた定義になっているが,これについては後述するので今は無視してもらって良い.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/07/call-arity-and-oneshot.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/07/call-arity-and-oneshot.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>DokuWiki の構文拡張プラグインの作り方2019-07-20T13:21:29+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-07-20:/blog/posts/2019/07/dokuwiki-syntax-plugin/<p>DokuWiki で Markdown が書けるプラグインを結構前に作った.で,たまにメンテしてるんだけど,そのメンテのために色々備忘録を残しておこうと思ったので,そのメモ.</p>
<div class="section" id="auto-id-1">
<h2>DokuWiki …</h2></div><p>DokuWiki で Markdown が書けるプラグインを結構前に作った.で,たまにメンテしてるんだけど,そのメンテのために色々備忘録を残しておこうと思ったので,そのメモ.</p>
<div class="section" id="auto-id-1">
<h2>DokuWiki のプラグイン作成<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>DokuWiki のプラグインの作成方法は, <a class="reference external" href="https://www.dokuwiki.org/devel:plugins">https://www.dokuwiki.org/devel:plugins</a> に大体まとまっている. DokuWiki では,以下の種類のプラグインを書ける.</p>
<dl class="docutils">
<dt>構文拡張プラグイン</dt>
<dd>文法を拡張するプラグイン.</dd>
<dt>動作拡張プラグイン</dt>
<dd>DokuWiki の動作を拡張するプラグイン. Wiki のページを作った際にテンプレートを適用したりできる.</dd>
<dt>管理者向けプラグイン</dt>
<dd>管理者の操作を拡張するプラグイン. Wiki のアップグレード画面を追加したりできる.</dd>
<dt>ヘルパープラグイン</dt>
<dd>他のプラグイン向けに関数を提供したりできる.</dd>
<dt>表示拡張プラグイン</dt>
<dd>DokuWiki の表示を拡張するプラグイン.</dd>
<dt>API拡張プラグイン</dt>
<dd>DokuWiki の API を拡張するプラグイン.どういうことができるのかはあんまり分かってない.</dd>
<dt>認証拡張プラグイン</dt>
<dd>新たに認証方式を追加できるプラグイン.</dd>
<dt>CLI拡張プラグイン</dt>
<dd>コマンドを新たに追加できるプラグイン.どういうことができるのかはあんまり分かってない.</dd>
</dl>
<p>各プラグインはそれぞれの名前にあった PHP ファイルを用意し,専用の抽象クラスを継承した具象クラスを作成することで,作成できる.今回対象にするのは構文拡張プラグイン.プラグインは,管理者ページの拡張機能管理画面から管理できる.インストールは, DokuWiki のパッケージインデックスから持ってくる方法とアーカイブファイルからインストール方法がある.</p>
<p>なおプラグインのファイル構造は, <a class="reference external" href="https://www.dokuwiki.org/devel:plugin_file_structure">https://www.dokuwiki.org/devel:plugin_file_structure</a> に載ってる通り.必須なのは <tt class="docutils literal">plugin.info.txt</tt> で,そこにプラグイン名や情報を書く.後は <tt class="docutils literal">conf</tt> ディレクトリに設定項目を書いたりする.</p>
<p>DokuWiki のパッケージインデックスは実はそんなに高等なものではなくて,単なる <a class="reference external" href="https://www.dokuwiki.org">本家のDokuWiki</a> にプラグインのページを探すだけ.プラグインの著者はアーカイブファイルのダウンロード URL を作成し,そのページに登録しておく.プラグインのインストールはそこから行われる.</p>
</div>
<div class="section" id="auto-id-3">
<h2>構文拡張プラグイン<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>構文拡張プラグイン (Syntax Plugin) の作り方は, <a class="reference external" href="https://www.dokuwiki.org/devel:syntax_plugins">https://www.dokuwiki.org/devel:syntax_plugins</a> に書いてある通り, <tt class="docutils literal">syntax.php</tt> という名前のファイルに <tt class="docutils literal">DokuWiki_Syntax_Plugin</tt> クラスを継承して <tt class="docutils literal">syntax_plugin_[プラグイン名]</tt> という名前のクラスを作る.このクラスは次のメソッドを実装する必要がある:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span></pre></div></td><td class="code"><div><pre><span></span><span class="cp"><?php</span>
<span class="nb">define</span><span class="p">(</span><span class="s1">'PLUGIN_NAME'</span><span class="p">,</span> <span class="s1">'example'</span><span class="p">);</span>
<span class="k">class</span> <span class="nc">syntax_plugin_example</span> <span class="k">extends</span> <span class="nx">DokuWiki_Syntax_Plugin</span> <span class="p">{</span>
<span class="c1">// パースの仕方を制御するための情報を返す.</span>
<span class="c1">// https://www.dokuwiki.org/devel:syntax_plugins#syntax_types に一覧がある.</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getType</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="s1">'protected'</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// 追加する構文の種類を制御する.</span>
<span class="c1">// 指定しない場合,インライン構文として認識される.</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getPType</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="s1">'block'</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// パースの優先度を設定する.</span>
<span class="c1">// 標準の優先度は https://www.dokuwiki.org/devel:parser:getsort_list に載ってる</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">getSort</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">69</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// 構文がマッチする条件を登録する.</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">connectTo</span><span class="p">(</span><span class="nv">$mode</span><span class="p">)</span> <span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="na">Lexer</span><span class="o">-></span><span class="na">addEntryPattern</span><span class="p">(</span><span class="s1">'<example>(?=.*</example>)'</span><span class="p">,</span> <span class="nv">$mode</span><span class="p">,</span> <span class="s1">'plugin_'</span> <span class="o">.</span> <span class="nx">PLUGIN_NAME</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// 構文が終了する条件を登録する.</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">postConnect</span><span class="p">()</span> <span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="na">Lexer</span><span class="o">-></span><span class="na">addExitPattern</span><span class="p">(</span><span class="s1">'</example>'</span><span class="p">,</span> <span class="s1">'plugin_'</span> <span class="o">.</span> <span class="nx">PLUGIN_NAME</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// マッチした内容を前処理する.</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">handle</span><span class="p">(</span><span class="nv">$match</span><span class="p">,</span> <span class="nv">$state</span><span class="p">,</span> <span class="nv">$pos</span><span class="p">,</span> <span class="nx">Doku_Handler</span> <span class="nv">$handler</span><span class="p">)</span> <span class="p">{</span>
<span class="k">switch</span> <span class="p">(</span><span class="nv">$state</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="nx">DOKU_LEXER_UNMATCHED</span><span class="o">:</span>
<span class="k">return</span> <span class="p">[</span>
<span class="s1">'render'</span> <span class="o">=></span> <span class="k">true</span><span class="p">,</span>
<span class="s1">'match'</span> <span class="o">=></span> <span class="nv">$match</span><span class="p">,</span>
<span class="p">];</span>
<span class="k">default</span><span class="o">:</span>
<span class="k">return</span> <span class="p">[</span>
<span class="s1">'render'</span> <span class="o">=></span> <span class="k">false</span><span class="p">,</span>
<span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// 前処理したデータをレンダリングする.</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">render</span><span class="p">(</span><span class="nv">$format</span><span class="p">,</span> <span class="nx">Doku_Renderer</span> <span class="nv">$renderer</span><span class="p">,</span> <span class="nv">$data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$data</span><span class="p">[</span><span class="s1">'render'</span><span class="p">])</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="nv">$match</span> <span class="o">=</span> <span class="nv">$data</span><span class="p">[</span><span class="s1">'match'</span><span class="p">];</span>
<span class="nv">$renderer</span><span class="o">-></span><span class="na">cdata</span><span class="p">(</span><span class="nv">$match</span><span class="p">);</span>
<span class="k">return</span> <span class="k">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>この場合, <tt class="docutils literal"><span class="pre"><example>...</example></span></tt> という構文が追加され,その中身をそのまま表示するようになる.</p>
</div>
<div class="section" id="api">
<h2>レンダラのAPI<a class="headerlink" href="#api" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal">render</tt> メソッドが受け取る <tt class="docutils literal">$renderer</tt> は,それぞれのレンダモードに対応したレンダリングを行う API をいくつか持っている. API は, <a class="reference external" href="https://xref.dokuwiki.org/reference/dokuwiki/nav.html?inc/parser/renderer.php.html#doku_renderer">https://xref.dokuwiki.org/reference/dokuwiki/nav.html?inc/parser/renderer.php.html#doku_renderer</a> に載ってる:</p>
<ul class="simple">
<li>table</li>
<li>list</li>
<li>horizontal line</li>
<li>strong</li>
</ul>
<p>など, HTML のいくつかのタグに対応するレンダAPIがあり,こいつらを使うと DokuWiki で使われてるスタイルに合わせたレンダリングができる.</p>
<p>レンダラは内部でバッファを持っていて,各APIはそれを更新していく.そいつに直接書き込むこともできる:</p>
<pre class="literal-block">
$renderer->doc .= 'something';
</pre>
<p>例えば XHTML モードの場合, <a class="reference external" href="https://xref.dokuwiki.org/reference/dokuwiki/nav.html?inc/parser/xhtml.php.source.html#l315">https://xref.dokuwiki.org/reference/dokuwiki/nav.html?inc/parser/xhtml.php.source.html#l315</a> を見れば分かる通り,大体は API の名前に対応する HTML タグをそのままバッファに追加してるだけ.</p>
<p>実際の DokuWiki がどういうレンダリングをするかは, <a class="reference external" href="https://xref.dokuwiki.org/reference/dokuwiki/nav.html?inc/parser/handler.php.source.html#l5">https://xref.dokuwiki.org/reference/dokuwiki/nav.html?inc/parser/handler.php.source.html#l5</a> をみれば分かる.例えばリンクの処理部分は, <a class="reference external" href="https://xref.dokuwiki.org/reference/dokuwiki/nav.html?inc/parser/handler.php.source.html#l527">https://xref.dokuwiki.org/reference/dokuwiki/nav.html?inc/parser/handler.php.source.html#l527</a> になる.URLと名前で区切って内部リンクか外部リンクかなどを判別して適切にレンダAPIを呼び出していく.APIの呼び出しは, 実際にはこのハンドラ内では呼び出されず,呼び出し登録が <tt class="docutils literal">_addCall</tt> というメソッドで行われているだけで,その後積まれた API 呼び出しの登録が実行されるようになっている.呼び出し登録は文書のデータ構造を把握する際に役に立つらしい <a class="footnote-reference" href="#instruction-for-analysis" id="auto-id-4">[1]</a> .例えば,</p>
<pre class="literal-block">
===== Read More =====
All documentation and additional information besides the [[syntax|syntax description]] is maintained in the DokuWiki at [[doku>|www.dokuwiki.org]].
</pre>
<p>のような DokuWiki の文書があった場合,</p>
<pre class="literal-block">
array(
array('document_start', array()),
array('header', array('Header', 2, 0)),
array('section_open', array(2)),
array('p_open', array()),
array('cdata', array("\nAll documentation and additional information besides the ")),
array('internallink', array('syntax', 'syntax description')),
array('cdata', array(' is maintained in the DokuWiki at ')),
array('internallink', array('doku>', 'www.dokuwiki.org')),
array('cdata', array('.')),
array('p_close', array()),
array('document_end', array()),
)
</pre>
<p>みたいな呼び出し登録が生成される.</p>
</div>
<div class="section" id="auto-id-5">
<h2>まとめ<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>DokuWiki のプラグイン開発ってかなり狭い領域だと思うけど,まあ誰かの参考になればという感じで.公式にも色々ドキュメントがあるのでのぞいてみると良さそう.て感じで.</p>
<table class="docutils footnote" frame="void" id="instruction-for-analysis" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[1]</a></td><td>実際にレンダリングをしてしまうと単なる文字列になってしまい,文書の構造の情報がなくなってしまうが,呼び出し登録は少なくともレンダラの API の呼び出し順序などが見れる.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/07/dokuwiki-syntax-plugin.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/07/dokuwiki-syntax-plugin.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>GHC の線形型プロトタイプのお試し環境を作る2019-06-28T10:09:22+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-06-28:/blog/posts/2019/06/linear-types-in-docker/<p>現在, GHC に <a class="reference external" href="https://github.com/ghc-proposals/ghc-proposals/pull/111">線形型の追加提案</a> が出ている.その提案に合わせて,プロトタイプも公開されている.内容はあまり詳しく追 …</p><p>現在, GHC に <a class="reference external" href="https://github.com/ghc-proposals/ghc-proposals/pull/111">線形型の追加提案</a> が出ている.その提案に合わせて,プロトタイプも公開されている.内容はあまり詳しく追ってないけど,お試し環境は作ってみたのでその備忘録.</p>
<div class="section" id="auto-id-2">
<h2>線形型プロトタイプ実装<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>線形型の提案は, GHC Proposals (<a class="reference external" href="https://github.com/ghc-proposals/ghc-proposals/pull/111">https://github.com/ghc-proposals/ghc-proposals/pull/111</a>) で議論されている. <a class="reference external" href="https://arxiv.org/abs/1710.09756">https://arxiv.org/abs/1710.09756</a> の話を元にしているらしい.プロトタイプ実装は, Tweag の GHC フォーク (<a class="reference external" href="https://github.com/tweag/ghc">https://github.com/tweag/ghc</a>) 内の <tt class="docutils literal"><span class="pre">linear-types</span></tt> ブランチで公開されている.</p>
<p>後,このプロトタイプを前提として,線形型用の <tt class="docutils literal">base</tt> 代替パッケージ, <tt class="docutils literal"><span class="pre">linear-base</span></tt> パッケージ (<a class="reference external" href="https://github.com/tweag/linear-base">https://github.com/tweag/linear-base</a>) も公開されている.中には</p>
<ul class="simple">
<li><tt class="docutils literal">Prelude.Linear</tt> : <tt class="docutils literal">Prelude</tt> の線形型版.色んな常用関数を線形型用に型を変えて提供してる.</li>
<li><tt class="docutils literal">Control.Monad.Linear</tt> : 線形型版のモナドを提供してる.</li>
<li><tt class="docutils literal">Control.Monad.Linear.Builder</tt> : 線形型版のモナドを <tt class="docutils literal">RebindableSyntax</tt> によって do 構文で使えるようにするためのデータを提供する.</li>
<li><tt class="docutils literal">System.IO.Linear</tt> : <tt class="docutils literal">IO</tt> モナドを線形型を使って厳密に定義し直したやつを提供する.</li>
<li><tt class="docutils literal">System.IO.Resource</tt> : リソース管理を線形型を使って型安全に行う仕組みを提供する.</li>
<li><tt class="docutils literal">Unsafe.Linear</tt> : 線形型と普通の関数型のキャストを提供する.</li>
</ul>
<p>みたいなモジュールがある (これが全部ではない).</p>
<p>プロトタイプの利用は GHC のビルドが必要だが,時間が相当かかるため,公開されてる Docker イメージで Stack の連動機能を使うことが推奨されている.</p>
</div>
<div class="section" id="docker">
<h2>お試し Docker 環境を作る<a class="headerlink" href="#docker" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ただ, Stack の連動機能を使わないで直接 Cabal を使って試したかったのでその環境を作った.公開されてる Docker イメージに, <tt class="docutils literal"><span class="pre">cabal-install</span></tt> を突っ込んで, <tt class="docutils literal"><span class="pre">linear-base</span></tt> パッケージを落としてきた状態にしただけだけど.</p>
<p>まず,次の <tt class="docutils literal">Dockerfile</tt> を用意する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">FROM</span><span class="w"> </span><span class="s">tweag/linear-types:latest</span>
<span class="k">ENV</span><span class="w"> </span><span class="nv">CABAL_WORKDIR</span><span class="o">=</span><span class="s2">"/root"</span>
<span class="k">RUN</span><span class="w"> </span>apt-get<span class="w"> </span>update<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nv">DEBIAN_FRONTEND</span><span class="o">=</span>noninteractive<span class="w"> </span>apt-get<span class="w"> </span>install<span class="w"> </span>-y<span class="w"> </span>curl<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span>mkdir<span class="w"> </span>-p<span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span><span class="s2">/.ghcup/bin"</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span>curl<span class="w"> </span>https://gitlab.haskell.org/haskell/ghcup/raw/master/ghcup<span class="w"> </span>><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span><span class="s2">/.ghcup/bin/ghcup"</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span>chmod<span class="w"> </span>+x<span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span><span class="s2">/.ghcup/bin/ghcup"</span><span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span><span class="s2">/.ghcup/bin/ghcup"</span><span class="w"> </span>install-cabal<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span>apt-get<span class="w"> </span>remove<span class="w"> </span>-y<span class="w"> </span>curl<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span>apt-get<span class="w"> </span>autoremove<span class="w"> </span>-y<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span>rm<span class="w"> </span>-rf<span class="w"> </span>/var/lib/apt/*
<span class="k">ENV</span><span class="w"> </span><span class="nv">PATH</span><span class="o">=</span><span class="s2">"</span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span><span class="s2">/.ghcup/bin:</span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span><span class="s2">/.cabal/bin:</span><span class="nv">$PATH</span><span class="s2">"</span>
<span class="k">ADD</span><span class="w"> </span>assets/Main.hs<span class="w"> </span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span>/Main.hs
<span class="k">ADD</span><span class="w"> </span>assets/cabal.project<span class="w"> </span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span>/cabal.project
<span class="k">ADD</span><span class="w"> </span>assets/playground.cabal<span class="w"> </span><span class="si">${</span><span class="nv">CABAL_WORKDIR</span><span class="si">}</span>/playground.cabal
<span class="k">WORKDIR</span><span class="w"> </span><span class="s">${CABAL_WORKDIR}</span>
<span class="k">RUN</span><span class="w"> </span>mkdir<span class="w"> </span>-p<span class="w"> </span>src<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span>cabal<span class="w"> </span>new-update<span class="w"> </span><span class="se">\</span>
<span class="w"> </span><span class="o">&&</span><span class="w"> </span>cabal<span class="w"> </span>new-build
<span class="k">ENTRYPOINT</span><span class="w"> </span><span class="p">[</span><span class="s2">"cabal"</span><span class="p">]</span>
<span class="k">CMD</span><span class="w"> </span><span class="p">[</span><span class="s2">"new-repl"</span><span class="p">]</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal"><span class="pre">tweag/linear-types</span></tt> が公開されてる Docker イメージで, Docker Hub に上がってる.こいつに <tt class="docutils literal">ghcup</tt> で <tt class="docutils literal"><span class="pre">cabal-install</span></tt> を入れてるだけ.後適当に次のファイルも用意しとく:</p>
<pre class="literal-block">
$ cat assets/Main.hs
module Main where
main :: IO ()
main = putStrLn "Hello"
$ cat assets/cabal.project
source-repository-package
type: git
location: https://github.com/tweag/linear-base.git
packages: ./
$ cat assets/playground.cabal
cabal-version: 2.4
name: playground
version: 0.0.0.1
build-type: Simple
common general
autogen-modules:
Paths_playground
other-modules:
Paths_playground
build-depends:
base >= 4.7 && < 5,
linear-base
ghc-options:
-Wall
-Wcompat
-Wincomplete-uni-patterns
-Wincomplete-record-updates
-Wredundant-constraints
-Wpartial-fields
-fprint-explicit-foralls
-fprint-potential-instances
-frefinement-level-hole-fits=1
-dcore-lint
default-language: Haskell2010
executable playground
import: general
hs-source-dirs: .
main-is: Main.hs
</pre>
<p>後は,イメージをビルドして tty 有効で起動してやると, <tt class="docutils literal"><span class="pre">linear-base</span></tt> が入った環境で REPL で色々できる.適当に <tt class="docutils literal"><span class="pre">docker-compose.yml</span></tt> も作っておく:</p>
<pre class="literal-block">
version: '3'
services:
playground:
build: .
volumes:
- ./Main.hs:/root/Main.hs
entrypoint: bash
command: ["-c", "tail -f /var/log/lastlog"]
</pre>
<p>これで,カレントディレクトリに <tt class="docutils literal">Main.hs</tt> を作って, Docker イメージ内でビルドしたり,読み込んだ状態で REPL 起動したりできる:</p>
<pre class="literal-block">
docker-compose up -d
docker-compose exec playground cabal new-build # ビルド
docker-compose exec playground cabal new-repl # REPL 起動
</pre>
</div>
<div class="section" id="auto-id-3">
<h2>動作確認<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>試しに,ちょっとしたサンプルを書いて動かしてみる.以下のようなサンプルを <tt class="docutils literal">Main.hs</tt> として用意した:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE BlockArguments #-}</span>
<span class="cm">{-# LANGUAGE OverloadedStrings #-}</span>
<span class="cm">{-# LANGUAGE RebindableSyntax #-}</span>
<span class="cm">{-# LANGUAGE RecordWildCards #-}</span>
<span class="kr">module</span><span class="w"> </span><span class="nn">Main</span><span class="w"> </span><span class="kr">where</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Prelude</span><span class="w"> </span><span class="k">hiding</span><span class="w"> </span><span class="p">(</span><span class="kt">Monad</span><span class="p">(</span><span class="o">..</span><span class="p">),</span><span class="w"> </span><span class="kt">MonadFail</span><span class="p">(</span><span class="o">..</span><span class="p">))</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Prelude.Linear</span><span class="w"> </span><span class="p">(</span><span class="kt">Unrestricted</span><span class="p">(</span><span class="o">..</span><span class="p">))</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">Control.Monad.Linear.Builder</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">Linear</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">System.IO</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">System</span>
<span class="kr">import</span><span class="w"> </span><span class="k">qualified</span><span class="w"> </span><span class="nn">System.IO.Resource</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="n">RIO</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Data.String</span><span class="w"> </span><span class="p">(</span><span class="nf">fromString</span><span class="p">)</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">run</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">writeSomething</span><span class="w"> </span><span class="s">"something.txt"</span>
<span class="nf">writeSomething</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">FilePath</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="kt">RIO</span><span class="w"> </span><span class="p">(</span><span class="kt">Unrestricted</span><span class="w"> </span><span class="nb">()</span><span class="p">)</span>
<span class="nf">writeSomething</span><span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">h0</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">openFile</span><span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="kt">System</span><span class="o">.</span><span class="kt">WriteMode</span>
<span class="w"> </span><span class="n">h1</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">hPutStr</span><span class="w"> </span><span class="n">h0</span><span class="w"> </span><span class="s">"some"</span>
<span class="w"> </span><span class="n">h2</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">hPutStr</span><span class="w"> </span><span class="n">h1</span><span class="w"> </span><span class="s">"thing"</span>
<span class="w"> </span><span class="kt">RIO</span><span class="o">.</span><span class="n">hClose</span><span class="w"> </span><span class="n">h2</span>
<span class="w"> </span><span class="n">return</span><span class="w"> </span><span class="p">(</span><span class="kt">Unrestricted</span><span class="w"> </span><span class="nb">()</span><span class="p">)</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="kt">Builder</span><span class="p">{</span><span class="o">..</span><span class="p">}</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Linear</span><span class="o">.</span><span class="n">monadBuilder</span>
</pre></div></td></tr></table></div>
<p>こいつを REPL で動かしてみる:</p>
<pre class="literal-block">
$ docker-compose exec playground cabal new-repl
>>> :m Main
>>> main
>>> readFile "something.txt"
"something"
>>> :q
</pre>
<p>ちゃんと動いてそう.なお,フルセットは <a class="reference external" href="https://github.com/mizunashi-mana/docker-ghc-linear-types">https://github.com/mizunashi-mana/docker-ghc-linear-types</a> に上げた.</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>線形型を試す環境を手に入れた.時間があったら色々試したいと思う.</p>
<p><tt class="docutils literal">Prelude.Linear</tt> が色々 <tt class="docutils literal">Prelude</tt> の記号と被せてきてるのは,正直微妙な気がする. <tt class="docutils literal">const</tt> とかはともかく演算子は名前変えて欲しい感がある.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/06/linear-types-in-docker.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/06/linear-types-in-docker.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Rust のジェネリック関数はどうコンパイルされるのか2019-06-24T08:29:50+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-06-24:/blog/posts/2019/06/rust-generics-inside/<p>最近, (特に境界条件を伴った) 多相関数が言語ごとにどういうコードを吐くかが気になったので, Haskell とコードの生成方 …</p><p>最近, (特に境界条件を伴った) 多相関数が言語ごとにどういうコードを吐くかが気になったので, Haskell とコードの生成方針が異なるという噂の Rust を見てみることにした.その覚え書き.なお, Rust 普段使いではないので間違ってるかもしれないのと,情報が古いかもしれない.</p>
<p><a class="reference external" href="https://rust-lang.github.io/rustc-guide/about-this-guide.html">https://rust-lang.github.io/rustc-guide/about-this-guide.html</a> が主な参考文献.使った <tt class="docutils literal">rustc</tt> は,</p>
<ul class="simple">
<li>rustc: <tt class="docutils literal"><span class="pre">1.37.0-nightly</span> (4edff843d <span class="pre">2019-06-16)</span></tt></li>
<li>cargo: <tt class="docutils literal"><span class="pre">1.37.0-nightly</span> (545f35425 <span class="pre">2019-05-23)</span></tt></li>
</ul>
<p>で, macOS で試してる.</p>
<div class="section" id="auto-id-1">
<h2>Rust のコンパイルフロー<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まず, Rust のコンパイルフローとその情報を見る方法について,確認する. Rust は大体以下の流れでコード生成をするっぽい.</p>
<ol class="arabic simple">
<li>ソースコードをパースして, AST に.</li>
<li>名前解決 / マクロ展開を行う.</li>
<li>AST を HIR (構文をより単純にしたもの) に変換.</li>
<li>型検査などの意味解析を行う.</li>
<li>HIR を MIR (借用の解析に適した中間言語) に変換.</li>
<li>借用検査及び最適化を行う <a class="footnote-reference" href="#mir-based-borrow-check" id="auto-id-2">[1]</a> .</li>
<li>MIR を LLVM IR に変換する.</li>
<li>LLVM でオブジェクトファイルを生成させる.</li>
<li>オブジェクトファイルを lld でリンクする.</li>
</ol>
<p>それぞれの中間言語を簡単に紹介しておくと,まず HIR は Rust の構文をやや削って単純化したもので,</p>
<ul class="simple">
<li>演算子の優先順位の概念はなく,括弧が必ずつく.</li>
<li><tt class="docutils literal">for</tt> や <tt class="docutils literal">if let</tt> といった構文がない.</li>
</ul>
<p>という感じになっている. <tt class="docutils literal">for</tt> や <tt class="docutils literal">if let</tt> は, <tt class="docutils literal">loop</tt> や <tt class="docutils literal">match</tt> , <tt class="docutils literal">let</tt> などを使って表現される.また,存在型が明確に入っていて,戻り値の型で使われる <tt class="docutils literal">impl Trait</tt> がこの型に変換されるらしい.ソースコードに対応する HIR を見たければ, nightly のみで使える <tt class="docutils literal">Z</tt> オプションを使って以下のようにする:</p>
<pre class="literal-block">
rustc -Zunpretty=hir source.rs
</pre>
<p>なお,内部で扱う生の木構造を見たかったら <tt class="docutils literal"><span class="pre">hir-tree</span></tt> ,型解決された後の型が明示されたものを見たかったら <tt class="docutils literal">hir,typed</tt> を <tt class="docutils literal"><span class="pre">-Zunpretty</span></tt> に渡せばいいっぽい.</p>
<p>MIR は,コード生成に寄せ,最適化のため制御フローグラフが明示された中間言語.制御フローグラフの各ノードを,ブロックとして囲んで, <tt class="docutils literal">goto</tt> 文や他幾つかのプリミティブ命令を取り入れ,ブロックからブロックの遷移をそれで表している.後,変数の使用範囲や <tt class="docutils literal">move</tt> なども明示されてる.こいつを表示したかったら以下のようにする:</p>
<pre class="literal-block">
rustc -Zunpretty=mir source.rs
</pre>
<p>Graphviz 向けに DOT 言語を使ってグラフの形で出力してくれるやつもあって, <tt class="docutils literal"><span class="pre">mir-cfg</span></tt> を <tt class="docutils literal"><span class="pre">-Zunpretty</span></tt> に渡すとそういう表示になる.</p>
<p>LLVM IR はまあ勝手知ったるものだと思うので,まあそういうやつです.以下のようにして出力ができる:</p>
<pre class="literal-block">
rustc --emit=llvm-ir -Ccodegen-units=1 source.rs
</pre>
<p>これを行うと <tt class="docutils literal">source.ll</tt> というファイルにコードが生成される.なお, <tt class="docutils literal">cargo</tt> を使う場合, <tt class="docutils literal"><span class="pre">cargo-asm</span></tt> プラグインを使うのが良いっぽい.こいつを使う場合,</p>
<pre class="literal-block">
cargo llvm-ir
</pre>
<p>で, LLVM IR での関数単位を表示してくれ,</p>
<pre class="literal-block">
cargo llvm-ir func
</pre>
<p>で, <tt class="docutils literal">func</tt> のコードが標準出力に表示できる.なお,デフォルトで表示されるのはリリースビルドになっているので,最適化があまりかかっていないものを見たかったら,</p>
<pre class="literal-block">
cargo llvm-ir --build-type=debug func
</pre>
<p>と指定するのが良さそう.</p>
<p>オブジェクトファイルも LLVM IR と同じように <tt class="docutils literal"><span class="pre">--emit=obj</span></tt> で出力でき, <tt class="docutils literal">source.o</tt> みたいなファイルが生成される.</p>
<p>なお, Rust はライブラリを <tt class="docutils literal">crate</tt> という単位で管理する.通常ビルドする時は,この <tt class="docutils literal">crate</tt> ごとにスタティックライブラリのアーカイブである <tt class="docutils literal">rlib</tt> ファイルを作る. <tt class="docutils literal">rlib</tt> ファイルは,</p>
<ul class="simple">
<li>オブジェクトファイル (<tt class="docutils literal">*.o</tt>)</li>
<li>LLVM のビットコード (<tt class="docutils literal">*.bc.z</tt>)</li>
<li>Rust 独自のメタデータ (<tt class="docutils literal">rust.metadata.bin</tt>)</li>
</ul>
<p>を含む <tt class="docutils literal">ar</tt> アーカイブになっている. <tt class="docutils literal">cargo</tt> でビルドする場合は, <tt class="docutils literal"><span class="pre">target/{debug,release}/deps/*.rlib</span></tt> に依存 <tt class="docutils literal">crate</tt> のライブラリが置かれるっぽい.で,メタデータの部分の解析が今回メインになるんだけど,こいつは単体でも出力できて, <tt class="docutils literal"><span class="pre">--emit=metadata</span></tt> とやると <tt class="docutils literal">libsource.rmeta</tt> みたいなファイルが生成される.</p>
</div>
<div class="section" id="auto-id-3">
<h2>Rust のジェネリック関数のコード生成アプローチ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Rust のジェネリック関数のコード生成方法の概要は, Rust Book の <a class="reference external" href="https://doc.rust-lang.org/1.35.0/book/ch10-01-syntax.html#performance-of-code-using-generics">Performance of Code Using Generics</a> で</p>
<blockquote>
<p>Rust accomplishes this by performing monomorphization of the code that is using generics at compile time. Monomorphization is the process of turning generic code into specific code by filling in the concrete types that are used when compiled.</p>
<p>In this process, the compiler does the opposite of the steps we used to create the generic function in Listing 10-5: the compiler looks at all the places where generic code is called and generates code for the concrete types the generic code is called with.</p>
</blockquote>
<p>と述べられている通り,</p>
<ol class="arabic simple">
<li>ジェネリック関数が使われている部分を全て探し出して,</li>
<li>その中から具象型で使われてる部分を抽出し,どの具象型で使われてるかを洗い出し,</li>
<li>それぞれの具象型に対して単相的なコードを埋め込み,</li>
<li>使われてる部分のジェネリック関数の呼び出しを埋め込んだ単相的な関数の呼び出しにすげ替える.</li>
</ol>
<p>つまり, C++ のテンプレートと同じアプローチを取る.もちろん単相的な関数を生成する為には,元のジェネリック関数の実装を知っている必要がある.ただ, Rust には C++ のようにヘッダと実装を分ける機能はない.なので,ジェネリック関数が <tt class="docutils literal">crate</tt> を超えて使われる場合,各 <tt class="docutils literal">crate</tt> は単にリンクするようのオブジェクトファイルを提供するだけでなく,自身が持っているジェネリック関数の実装をメタデータとして渡してやる必要がある.ついでに,渡してやる必要のあるデータは他にも幾つかある.詳細は後で見る.</p>
<p>とりあえず,本当に単相的なコードを埋め込んでいるかのちょっとした確認をしておく.次のようなコードを用意する:</p>
<pre class="literal-block">
// monomorphization.rs
pub fn generic_func<T>(x: T) -> T {
x
}
pub fn test_func1() -> i32 {
generic_func(0)
}
pub fn test_func2() -> i32 {
generic_func(333)
}
pub fn test_func3() -> Option<i32> {
generic_func(None)
}
</pre>
<p>こいつに対応する LLVM IR を見てみる:</p>
<pre class="literal-block">
$ rustc --emit=llvm-ir -Ccodegen-units=1 --crate-type=lib monomorphization.rs
$ cat monomorphization.ll
...
; monomorphization::generic_func
; Function Attrs: uwtable
define i32 @_ZN16monomorphization12generic_func17h4e8466f957c62c4dE(i32 %x) unnamed_addr #0 {
start:
ret i32 %x
}
; monomorphization::generic_func
; Function Attrs: uwtable
define { i32, i32 } @_ZN16monomorphization12generic_func17hdce2324413889031E(i32 %x.0, i32 %x.1) unnamed_addr #0 {
start:
%0 = insertvalue { i32, i32 } undef, i32 %x.0, 0
%1 = insertvalue { i32, i32 } %0, i32 %x.1, 1
ret { i32, i32 } %1
}
; monomorphization::test_func1
; Function Attrs: uwtable
define i32 @_ZN16monomorphization10test_func117hd71db534fc9d7a5fE() unnamed_addr #0 {
start:
; call monomorphization::generic_func
%0 = call i32 @_ZN16monomorphization12generic_func17h4e8466f957c62c4dE(i32 0)
br label %bb1
bb1: ; preds = %start
ret i32 %0
}
; monomorphization::test_func2
; Function Attrs: uwtable
define i32 @_ZN16monomorphization10test_func217h14aba5cafddf6defE() unnamed_addr #0 {
start:
; call monomorphization::generic_func
%0 = call i32 @_ZN16monomorphization12generic_func17h4e8466f957c62c4dE(i32 333)
br label %bb1
bb1: ; preds = %start
ret i32 %0
}
; monomorphization::test_func3
; Function Attrs: uwtable
define { i32, i32 } @_ZN16monomorphization10test_func317h7ff127b737116f48E() unnamed_addr #0 {
start:
%_1 = alloca { i32, i32 }, align 4
%0 = bitcast { i32, i32 }* %_1 to i32*
store i32 0, i32* %0, align 4
%1 = getelementptr inbounds { i32, i32 }, { i32, i32 }* %_1, i32 0, i32 0
%2 = load i32, i32* %1, align 4, !range !0
%3 = getelementptr inbounds { i32, i32 }, { i32, i32 }* %_1, i32 0, i32 1
%4 = load i32, i32* %3, align 4
; call monomorphization::generic_func
%5 = call { i32, i32 } @_ZN16monomorphization12generic_func17hdce2324413889031E(i32 %2, i32 %4)
%6 = extractvalue { i32, i32 } %5, 0
%7 = extractvalue { i32, i32 } %5, 1
br label %bb1
bb1: ; preds = %start
%8 = insertvalue { i32, i32 } undef, i32 %6, 0
%9 = insertvalue { i32, i32 } %8, i32 %7, 1
ret { i32, i32 } %9
}
...
</pre>
<p>見ての通り, <tt class="docutils literal">i32</tt> と <tt class="docutils literal">Option<i32></tt> 用にそれぞれ <tt class="docutils literal">generic_func</tt> のコードが生成されていて, <tt class="docutils literal">test_func1</tt> と <tt class="docutils literal">test_func2</tt> は <tt class="docutils literal">i32</tt> 用のを, <tt class="docutils literal">test_func3</tt> は <tt class="docutils literal">Option<i32></tt> 用のを呼んでることが分かる.</p>
</div>
<div class="section" id="auto-id-4">
<h2>メタデータの内容<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>メタデータは, Rust コンパイラの <a class="reference external" href="https://github.com/rust-lang/rust/tree/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_metadata">rustc_metadata crate</a> で取り扱っているっぽい.まだ,よく分かってない部分もあるんだけど,メタデータは大体以下のフォーマットになってるっぽい:</p>
<ol class="arabic">
<li><p class="first">最初の 7 byte はヘッダで, <tt class="docutils literal">[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0]</tt> (<tt class="docutils literal">0000 0000 7275 7374 0000 00</tt>) 固定.</p>
</li>
<li><p class="first">次の 1 byte はフォーマットバージョンで,現状はバージョン 4 (<tt class="docutils literal">04</tt>)</p>
</li>
<li><p class="first">次の 4 byte は,書き込んだバイト数が入っている.</p>
</li>
<li><p class="first">次はビルドに使った <tt class="docutils literal">rustc</tt> のバージョンが, <tt class="docutils literal">String</tt> をシリアライズした形で埋め込まれている.つまり,最初に文字列の長さ,次にその本体が続く感じ.ただし, <tt class="docutils literal">usize</tt> 型の文字列の長さは, LEB128 エンコードされていて,短い文字列なら 1 byte で表現される.今回の環境では,</p>
<pre class="literal-block">
2b72 7573 7463 2031 2e33 372e 302d 6e69 +rustc 1.37.0-ni
6768 746c 7920 2834 6564 6666 3834 3364 ghtly (4edff843d
2032 3031 392d 3036 2d31 3629 2019-06-16)
</pre>
<p>となっていた. <tt class="docutils literal">0x2b = 43</tt> なので合ってそう.</p>
</li>
<li><p class="first">次に <a class="reference external" href="https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_metadata/schema.rs#L156">CrateRoot</a> をシリアライズしたものが,埋め込まれる.</p>
</li>
</ol>
<p>メタデータのエンコードは次の関数を用いるっぽい:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">// https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_metadata/encoder.rs#L1866</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">encode_metadata</span><span class="o"><'</span><span class="na">tcx</span><span class="o">></span><span class="p">(</span><span class="n">tcx</span>: <span class="nc">TyCtxt</span><span class="o"><'</span><span class="na">tcx</span><span class="o">></span><span class="p">)</span><span class="w"> </span>-> <span class="nc">EncodedMetadata</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">TyCtxt</tt> は typing context と呼ばれてるけど,ぶっちゃけ色々入ってるやつ.多分 <tt class="docutils literal">crate</tt> ごとに一つ用意されていて, <tt class="docutils literal">crate</tt> の情報と型情報などが入っている. <tt class="docutils literal">EncodedMetadata</tt> はメタデータがバイト列にエンコードされたものを表す型だけど,実体はただの <tt class="docutils literal">Vec<u8></tt> の newtype になっている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">// https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc/middle/cstore.rs#L150</span>
<span class="k">pub</span><span class="w"> </span><span class="k">struct</span> <span class="nc">EncodedMetadata</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="n">raw_data</span>: <span class="nb">Vec</span><span class="o"><</span><span class="kt">u8</span><span class="o">></span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>この関数の主要部分は <tt class="docutils literal"><span class="pre">ecx.encode_crate_root();</span></tt> で,ここで <tt class="docutils literal">CrateRoot</tt> のシリアライズを行なっている.デコードは,次の部分でやるっぽい:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">// https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_metadata/decoder.rs#L369</span>
<span class="k">impl</span><span class="o"><'</span><span class="na">tcx</span><span class="o">></span><span class="w"> </span><span class="n">MetadataBlob</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">is_compatible</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="kt">bool</span> <span class="p">{</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">get_rustc_version</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nb">String</span> <span class="p">{</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">get_root</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nc">CrateRoot</span><span class="o"><'</span><span class="na">tcx</span><span class="o">></span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">list_crate_metadata</span><span class="p">(</span><span class="o">&</span><span class="bp">self</span><span class="p">,</span>
<span class="w"> </span><span class="n">out</span>: <span class="kp">&</span><span class="nc">mut</span><span class="w"> </span><span class="k">dyn</span><span class="w"> </span><span class="n">io</span>::<span class="n">Write</span><span class="p">)</span><span class="w"> </span>-> <span class="nc">io</span>::<span class="nb">Result</span><span class="o"><</span><span class="p">()</span><span class="o">></span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">..</span><span class="p">.</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">MetadataBlob</tt> はメタデータのバイトフォーマットデータを表すデータ型で,やはり実体は <tt class="docutils literal">u8</tt> 列のスライスになっている.ただ,こっちは高速化のため色々やってるっぽくて,その為の保証情報も付随してる.それぞれのメソッドは,</p>
<ul class="simple">
<li><tt class="docutils literal">is_compatible</tt>: メタデータのヘッダとバージョンチェック</li>
<li><tt class="docutils literal">get_rustc_version</tt>: <tt class="docutils literal">rustc</tt> のバージョンをデシリアライズして取得</li>
<li><tt class="docutils literal">get_root</tt>: <tt class="docutils literal">CrateRoot</tt> をデシリアライズして取得</li>
<li><tt class="docutils literal">list_crate_metadata</tt>: <tt class="docutils literal">get_root</tt> で取ってきた <tt class="docutils literal">CrateRoot</tt> から,外部ファイルで依存している名前を一覧表示 <a class="footnote-reference" href="#list-crate-metadata-usecase" id="auto-id-5">[2]</a> .</li>
</ul>
<p>という感じっぽい.で,肝心のどういう情報が載ってるかだけど,それは <tt class="docutils literal">CrateRoot</tt> の定義を見れば良くて,フィールドの名前から推察する限り,以下の情報が入ってそう.</p>
<ul class="simple">
<li><tt class="docutils literal">crate</tt> の情報 (名前 / ターゲット / エディションなど)</li>
<li>外部やネイティブライブラリへの依存関係</li>
<li>trait の実装やエクスポートしているシンボル情報</li>
<li><tt class="docutils literal">entries_index</tt></li>
</ul>
<p>で, <tt class="docutils literal">entries_index</tt> が今回重要な情報で,こいつには <a class="reference external" href="https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_metadata/schema.rs#L211">Entry</a> 要素が格納されている位置がたくさん詰め込まれている. <tt class="docutils literal">Entry</tt> は以下の種類のデータを持っているっぽい:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">// https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_metadata/schema.rs#L231</span>
<span class="k">pub</span><span class="w"> </span><span class="k">enum</span> <span class="nc">EntryKind</span><span class="o"><'</span><span class="na">tcx</span><span class="o">></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Const</span><span class="p">(</span><span class="n">ConstQualif</span><span class="p">,</span><span class="w"> </span><span class="n">Lazy</span><span class="o"><</span><span class="n">RenderedConst</span><span class="o">></span><span class="p">),</span>
<span class="w"> </span><span class="n">ImmStatic</span><span class="p">,</span>
<span class="w"> </span><span class="n">MutStatic</span><span class="p">,</span>
<span class="w"> </span><span class="n">ForeignImmStatic</span><span class="p">,</span>
<span class="w"> </span><span class="n">ForeignMutStatic</span><span class="p">,</span>
<span class="w"> </span><span class="n">ForeignMod</span><span class="p">,</span>
<span class="w"> </span><span class="n">ForeignType</span><span class="p">,</span>
<span class="w"> </span><span class="n">GlobalAsm</span><span class="p">,</span>
<span class="w"> </span><span class="n">Type</span><span class="p">,</span>
<span class="w"> </span><span class="n">TypeParam</span><span class="p">,</span>
<span class="w"> </span><span class="n">ConstParam</span><span class="p">,</span>
<span class="w"> </span><span class="n">Existential</span><span class="p">,</span>
<span class="w"> </span><span class="n">Enum</span><span class="p">(</span><span class="n">ReprOptions</span><span class="p">),</span>
<span class="w"> </span><span class="n">Field</span><span class="p">,</span>
<span class="w"> </span><span class="n">Variant</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">VariantData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="w"> </span><span class="n">Struct</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">VariantData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">,</span><span class="w"> </span><span class="n">ReprOptions</span><span class="p">),</span>
<span class="w"> </span><span class="n">Union</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">VariantData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">,</span><span class="w"> </span><span class="n">ReprOptions</span><span class="p">),</span>
<span class="w"> </span><span class="nb">Fn</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">FnData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="w"> </span><span class="n">ForeignFn</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">FnData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="w"> </span><span class="n">Mod</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">ModData</span><span class="o">></span><span class="p">),</span>
<span class="w"> </span><span class="n">MacroDef</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">MacroDef</span><span class="o">></span><span class="p">),</span>
<span class="w"> </span><span class="n">Closure</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">ClosureData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="w"> </span><span class="n">Generator</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">GeneratorData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="w"> </span><span class="n">Trait</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">TraitData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="w"> </span><span class="n">Impl</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">ImplData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="w"> </span><span class="n">Method</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">MethodData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="w"> </span><span class="n">AssocType</span><span class="p">(</span><span class="n">AssocContainer</span><span class="p">),</span>
<span class="w"> </span><span class="n">AssocExistential</span><span class="p">(</span><span class="n">AssocContainer</span><span class="p">),</span>
<span class="w"> </span><span class="n">AssocConst</span><span class="p">(</span><span class="n">AssocContainer</span><span class="p">,</span><span class="w"> </span><span class="n">ConstQualif</span><span class="p">,</span><span class="w"> </span><span class="n">Lazy</span><span class="o"><</span><span class="n">RenderedConst</span><span class="o">></span><span class="p">),</span>
<span class="w"> </span><span class="n">TraitAlias</span><span class="p">(</span><span class="n">Lazy</span><span class="o"><</span><span class="n">TraitAliasData</span><span class="o"><'</span><span class="na">tcx</span><span class="o">>></span><span class="p">),</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>で,全種類において,可視性 / 属性 / 安定性情報や,型情報 / ジェネリクス / 境界条件の情報,本体の MIR コードなどが入っているっぽい.</p>
</div>
<div class="section" id="mir">
<h2>メタデータの MIR を確認する<a class="headerlink" href="#mir" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal">rustc</tt> の nightly 版には, <tt class="docutils literal">rustc_private</tt> という feature が用意されていて,それを使うと <tt class="docutils literal">rustc</tt> 内の crate を使える.それを使えば何とかなると思ったんだけど,なんか色々辛くて,コンパイラに直接コードを埋め込むことにした.</p>
<p><tt class="docutils literal">rustc</tt> のコンパイラ本体コードは, <a class="reference external" href="https://github.com/rust-lang/rust/tree/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_driver">rustc_driver crate</a> で扱っているっぽい.ここの <a class="reference external" href="https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_driver/lib.rs#L124">run_compiler</a> に次のコードを追加する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span></pre></div></td><td class="code"><div><pre><span></span><span class="o">..</span><span class="p">.</span>
<span class="k">use</span><span class="w"> </span><span class="n">rustc</span>::<span class="n">hir</span>::<span class="n">def_id</span>::<span class="n">DefIndex</span><span class="p">;</span>
<span class="k">use</span><span class="w"> </span><span class="n">rustc</span>::<span class="n">hir</span>::<span class="n">def</span>::<span class="n">DefKind</span><span class="p">;</span>
<span class="k">use</span><span class="w"> </span><span class="n">rustc_mir</span>::<span class="n">util</span>::<span class="n">pretty</span>::<span class="n">write_basic_block</span><span class="p">;</span>
<span class="o">..</span><span class="p">.</span>
<span class="k">if</span><span class="w"> </span><span class="n">sess</span><span class="p">.</span><span class="n">opts</span><span class="p">.</span><span class="n">debugging_opts</span><span class="p">.</span><span class="n">save_analysis</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">mem</span>::<span class="nb">drop</span><span class="p">(</span><span class="n">compiler</span><span class="p">.</span><span class="n">expansion</span><span class="p">()</span><span class="o">?</span><span class="p">.</span><span class="n">take</span><span class="p">());</span>
<span class="p">}</span>
<span class="c1">// inspect crate metadata code</span>
<span class="c1">//----------------------------------------</span>
<span class="n">compiler</span><span class="p">.</span><span class="n">cstore</span><span class="p">().</span><span class="n">iter_crate_data</span><span class="p">(</span><span class="o">|</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">cmeta</span><span class="o">|</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">crate_name_str</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">from</span><span class="p">(</span><span class="n">cmeta</span><span class="p">.</span><span class="n">name</span><span class="p">.</span><span class="n">as_str</span><span class="p">().</span><span class="n">get</span><span class="p">());</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">target_crate_name_prefix</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"monomorphization_"</span><span class="p">;</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">crate_name_str</span><span class="p">.</span><span class="n">starts_with</span><span class="p">(</span><span class="n">target_crate_name_prefix</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">idx_num</span>: <span class="kt">u32</span> <span class="o">=</span><span class="w"> </span><span class="n">crate_name_str</span><span class="p">[</span><span class="n">target_crate_name_prefix</span><span class="p">.</span><span class="n">len</span><span class="p">()</span><span class="o">..</span><span class="p">]</span>
<span class="w"> </span><span class="p">.</span><span class="n">parse</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()</span>
<span class="w"> </span><span class="p">;</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">def_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">DefIndex</span>::<span class="n">from</span><span class="p">(</span><span class="n">idx_num</span><span class="p">);</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="n">entry_name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmeta</span><span class="p">.</span><span class="n">item_name</span><span class="p">(</span><span class="n">def_index</span><span class="p">).</span><span class="n">as_str</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">DefKind</span>::<span class="nb">Fn</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmeta</span><span class="p">.</span><span class="n">def_kind</span><span class="p">(</span><span class="n">def_index</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">compiler</span><span class="p">.</span><span class="n">global_ctxt</span><span class="p">().</span><span class="n">unwrap</span><span class="p">().</span><span class="n">peek_mut</span><span class="p">().</span><span class="n">enter</span><span class="p">(</span><span class="o">|</span><span class="n">tcx</span><span class="o">|</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"{}: {}"</span><span class="p">,</span><span class="w"> </span><span class="n">entry_name</span><span class="p">,</span><span class="w"> </span><span class="n">cmeta</span><span class="p">.</span><span class="n">fn_sig</span><span class="p">(</span><span class="n">def_index</span><span class="p">,</span><span class="w"> </span><span class="n">tcx</span><span class="p">));</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">body</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cmeta</span><span class="p">.</span><span class="n">maybe_get_optimized_mir</span><span class="p">(</span><span class="n">tcx</span><span class="p">,</span><span class="w"> </span><span class="n">def_index</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">block</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">body</span><span class="p">.</span><span class="n">basic_blocks</span><span class="p">().</span><span class="n">indices</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">write_basic_block</span><span class="p">(</span><span class="n">tcx</span><span class="p">,</span><span class="w"> </span><span class="n">block</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="n">body</span><span class="p">,</span><span class="w"> </span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="o">|</span><span class="n">_</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="o">|</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(()),</span><span class="w"> </span><span class="o">&</span><span class="k">mut</span><span class="w"> </span><span class="n">io</span>::<span class="n">stdout</span><span class="p">()).</span><span class="n">unwrap</span><span class="p">();</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">block</span><span class="p">.</span><span class="n">index</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">body</span><span class="p">.</span><span class="n">basic_blocks</span><span class="p">().</span><span class="n">len</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">""</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"Cannot found MIR body."</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">});</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"{}: This entry is not function."</span><span class="p">,</span><span class="w"> </span><span class="n">entry_name</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">});</span>
<span class="c1">//----------------------------------------</span>
<span class="n">compiler</span><span class="p">.</span><span class="n">ongoing_codegen</span><span class="p">()</span><span class="o">?</span><span class="p">;</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">compiler.cstore()</tt> は <tt class="docutils literal">CrateStore</tt> データが入っており,こいつに crate のメタデータが詰め込まれている.こいつから</p>
<ol class="arabic simple">
<li>中身のクレートをそれぞれ見て,名前が <tt class="docutils literal"><span class="pre">monomorphization_[0-9]*</span></tt> となっているものを引っ張ってくる.</li>
<li>後ろに付いている番号を <tt class="docutils literal">Entry</tt> のインデックスとして,メタデータからそのエントリの情報をもらってくる.</li>
<li>エントリの中身を表示する.</li>
</ol>
<p>ということをする.ただ, <tt class="docutils literal">Entry</tt> 自体はパブリックに使えないデータになっていて, <tt class="docutils literal">EntryKind</tt> も同様なので直接は扱えない.で, <tt class="docutils literal">EntryKind</tt> に相当するパブリックなデータ型があり,それが <tt class="docutils literal">DefKind</tt> .一回こいつでエントリの種別を取得し,関数ならその関数の型シグネチャと MIR コードを表示する.ただこいつらの取得には <tt class="docutils literal">TyCtxt</tt> が必要になる.こいつはスレッドローカルストレージに格納されていて,取り出すときは色々面倒な操作が必要になる.それを取り出してるのが, <tt class="docutils literal"><span class="pre">compiler.global_ctxt().unwrap().peek_mut().enter(|tcx|</span> { ... })</tt> の部分.後, MIR は制御フローグラフのノード (ブロック) の塊になっているので,そいつをいい感じに表示するためのコードも入れてる.ただ,このコードはこれだけでは動かなくって, <a class="reference external" href="https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_metadata/cstore.rs#L135">CrateStore.iter_crate_data</a> と <a class="reference external" href="https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_mir/util/pretty.rs#L302">write_basic_block</a> が必要になるためこいつをパブリックにした:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span>// https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_metadata/cstore.rs#L135
<span class="gd">- pub(super) fn iter_crate_data<I>(&self, mut i: I)</span>
<span class="gi">+ pub fn iter_crate_data<I>(&self, mut i: I)</span>
// https://github.com/rust-lang/rust/blob/4edff843dd219cf19a5fede6c78c7ce95402e1f5/src/librustc_mir/util/mod.rs#L13
<span class="gd">- pub(super) mod pretty</span>
<span class="gi">+ pub mod pretty</span>
</pre></div></td></tr></table></div>
<p>で,このコードを埋め込んで <tt class="docutils literal">rustc</tt> をコンパイルする. <a class="reference external" href="https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html">https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html</a> の通りに,</p>
<pre class="literal-block">
cp config.toml.example config.toml
sed -ie 's/#debug = false/debug = true/' config.toml
./x.py build
</pre>
<p>みたいなことをすればいい.なお,実際に使った <tt class="docutils literal">config.toml</tt> は以下の感じ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span>
<span class="normal">48</span>
<span class="normal">49</span>
<span class="normal">50</span>
<span class="normal">51</span>
<span class="normal">52</span>
<span class="normal">53</span>
<span class="normal">54</span>
<span class="normal">55</span>
<span class="normal">56</span>
<span class="normal">57</span>
<span class="normal">58</span>
<span class="normal">59</span>
<span class="normal">60</span>
<span class="normal">61</span>
<span class="normal">62</span>
<span class="normal">63</span>
<span class="normal">64</span>
<span class="normal">65</span>
<span class="normal">66</span>
<span class="normal">67</span>
<span class="normal">68</span>
<span class="normal">69</span>
<span class="normal">70</span>
<span class="normal">71</span>
<span class="normal">72</span>
<span class="normal">73</span>
<span class="normal">74</span>
<span class="normal">75</span>
<span class="normal">76</span>
<span class="normal">77</span>
<span class="normal">78</span>
<span class="normal">79</span>
<span class="normal">80</span>
<span class="normal">81</span>
<span class="normal">82</span>
<span class="normal">83</span>
<span class="normal">84</span></pre></div></td><td class="code"><div><pre><span></span><span class="gd">--- config.toml.example</span>
<span class="gi">+++ config.toml</span>
<span class="gu">@@ -27,7 +27,7 @@</span>
<span class="w"> </span>#release-debuginfo = false
<span class="w"> </span># Indicates whether the LLVM assertions are enabled or not
<span class="gd">-#assertions = false</span>
<span class="gi">+assertions = true</span>
<span class="w"> </span># Indicates whether ccache is used when building LLVM
<span class="w"> </span>#ccache = false
<span class="gu">@@ -136,7 +136,7 @@</span>
<span class="w"> </span># Flag to specify whether any documentation is built. If false, rustdoc and
<span class="w"> </span># friends will still be compiled but they will not be used to generate any
<span class="w"> </span># documentation.
<span class="gd">-#docs = true</span>
<span class="gi">+docs = false</span>
<span class="w"> </span># Indicate whether the compiler should be documented in addition to the standard
<span class="w"> </span># library and facade crates.
<span class="gu">@@ -263,7 +263,7 @@</span>
<span class="w"> </span># Note: the slowness of the non optimized compiler compiling itself usually
<span class="w"> </span># outweighs the time gains in not doing optimizations, therefore a
<span class="w"> </span># full bootstrap takes much more time with `optimize` set to false.
<span class="gd">-#optimize = true</span>
<span class="gi">+optimize = true</span>
<span class="w"> </span># Indicates that the build should be configured for debugging Rust. A
<span class="w"> </span># `debug`-enabled compiler and standard library will be somewhat
<span class="gu">@@ -286,7 +286,7 @@</span>
<span class="w"> </span># "maximally debuggable" environment (notably libstd) takes
<span class="w"> </span># hours to build.
<span class="w"> </span>#
<span class="gd">-#debug = false</span>
<span class="gi">+debug = true</span>
<span class="w"> </span># Number of codegen units to use for each compiler invocation. A value of 0
<span class="w"> </span># means "the number of cores on this machine", and 1+ is passed through to the
<span class="gu">@@ -324,10 +324,10 @@</span>
<span class="w"> </span>#debuginfo-level-tests = 0
<span class="w"> </span># Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
<span class="gd">-#backtrace = true</span>
<span class="gi">+backtrace = true</span>
<span class="w"> </span># Whether to always use incremental compilation when building rustc
<span class="gd">-#incremental = false</span>
<span class="gi">+incremental = true</span>
<span class="w"> </span># Build a multi-threaded rustc
<span class="w"> </span>#parallel-compiler = false
<span class="gu">@@ -340,7 +340,7 @@</span>
<span class="w"> </span># The "channel" for the Rust build to produce. The stable/beta channels only
<span class="w"> </span># allow using stable features, whereas the nightly and dev channels allow using
<span class="w"> </span># nightly features
<span class="gd">-#channel = "dev"</span>
<span class="gi">+channel = "dev"</span>
<span class="w"> </span># By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix
<span class="w"> </span># platforms to ensure that the compiler is usable by default from the build
<span class="gu">@@ -353,12 +353,12 @@</span>
<span class="w"> </span>#verbose-tests = false
<span class="w"> </span># Flag indicating whether tests are compiled with optimizations (the -O flag).
<span class="gd">-#optimize-tests = true</span>
<span class="gi">+optimize-tests = false</span>
<span class="w"> </span># Flag indicating whether codegen tests will be run or not. If you get an error
<span class="w"> </span># saying that the FileCheck executable is missing, you may want to disable this.
<span class="w"> </span># Also see the target's llvm-filecheck option.
<span class="gd">-#codegen-tests = true</span>
<span class="gi">+codegen-tests = false</span>
<span class="w"> </span># Flag indicating whether git info will be retrieved from .git automatically.
<span class="w"> </span># Having the git information can cause a lot of rebuilds during development.
<span class="gu">@@ -408,7 +408,7 @@</span>
<span class="w"> </span>#deny-warnings = true
<span class="w"> </span># Print backtrace on internal compiler errors during bootstrap
<span class="gd">-#backtrace-on-ice = false</span>
<span class="gi">+backtrace-on-ice = true</span>
<span class="w"> </span># Whether to verify generated LLVM IR
<span class="w"> </span>#verify-llvm-ir = false
</pre></div></td></tr></table></div>
<p>なお, <tt class="docutils literal">rustup</tt> でこのビルドしたコンパイラを,次のように登録できるらしい:</p>
<pre class="literal-block">
rustup toolchain link local-build build/x86_64*/stage2
</pre>
<p>便利だ.後は使いたいディレクトリで <tt class="docutils literal">rustup override set <span class="pre">local-build</span></tt> とかすればいい.で,まず <tt class="docutils literal"><span class="pre">hir-tree</span></tt> からみたいエントリのインデックスを特定する:</p>
<pre class="literal-block">
$ rustc -Zunpretty=hir-tree monomorphization.rs
...
HirId {
owner: DefIndex(12),
local_id: 0,
}: Item {
ident: generic_func#0,
hir_id: HirId {
owner: DefIndex(12),
local_id: 0,
},
attrs: [],
node: Fn(
FnDecl {
inputs: [
type(T),
],
output: Return(
type(T),
),
c_variadic: false,
implicit_self: None,
},
...
</pre>
<p><tt class="docutils literal">generic_func</tt> は 12 番っぽい.この番号を元に次のようにして,メタデータを見る:</p>
<pre class="literal-block">
$ rustc --crate-type=lib --crate-name=monomorphization_12 monomorphization.rs
$ cat > main.rs
extern crate monomorphization_12;
fn main() {
println!("{:?}", monomorphization_12::generic_func(0));
}
$ rustc -L . main.rs
generic_func: fn(T) -> T
bb0: {
_0 = move _1; // bb0[0]: scope 0 at monomorphization.rs:4:3: 4:4
return; // bb0[1]: scope 0 at monomorphization.rs:5:2: 5:2
}
</pre>
<p>このコードが,元の <tt class="docutils literal">monomorphization.rs</tt> の <tt class="docutils literal">generic_func</tt> 関数の MIR コードと一致することは,以下のように確認できる:</p>
<pre class="literal-block">
$ rustc --crate-type=lib -Zunpretty=mir monomorphization.rs
...
fn generic_func(_1: T) -> T {
let mut _0: T; // return place in scope 0 at monomorphization.rs:3:33: 3:34
bb0: {
_0 = move _1; // bb0[0]: scope 0 at monomorphization.rs:4:3: 4:4
return; // bb0[1]: scope 0 at monomorphization.rs:5:2: 5:2
}
}
...
</pre>
</div>
<div class="section" id="auto-id-6">
<h2>境界条件を伴ったジェネリック関数<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>トレイトの境界条件が付いた場合は,どのようなコードが生成されるかも見てみる.まず,次のコードを用意する:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">// trait_monomorphization.rs</span>
<span class="k">pub</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">TestTrait</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">test_trait_func</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nc">Self</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">generic_trait_func</span><span class="o"><</span><span class="n">T</span>: <span class="nc">TestTrait</span><span class="o">></span><span class="p">(</span><span class="n">x</span>: <span class="nc">T</span><span class="p">)</span><span class="w"> </span>-> <span class="nc">T</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="n">test_trait_func</span><span class="p">()</span>
<span class="p">}</span>
<span class="k">impl</span><span class="w"> </span><span class="n">TestTrait</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">test_trait_func</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nc">Self</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="bp">self</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="k">impl</span><span class="w"> </span><span class="n">TestTrait</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="nb">Option</span><span class="o"><</span><span class="kt">i32</span><span class="o">></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">fn</span> <span class="nf">test_trait_func</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-> <span class="nc">Self</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="bp">self</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">test_func1</span><span class="p">()</span><span class="w"> </span>-> <span class="kt">i32</span> <span class="p">{</span>
<span class="w"> </span><span class="n">generic_trait_func</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">test_func2</span><span class="p">()</span><span class="w"> </span>-> <span class="kt">i32</span> <span class="p">{</span>
<span class="w"> </span><span class="n">generic_trait_func</span><span class="p">(</span><span class="mi">333</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">test_func3</span><span class="p">()</span><span class="w"> </span>-> <span class="nb">Option</span><span class="o"><</span><span class="kt">i32</span><span class="o">></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">generic_trait_func</span><span class="p">(</span><span class="nb">None</span><span class="p">)</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>こいつの, MIR コードは以下のようになる:</p>
<pre class="literal-block">
$ rustc --crate-type lib -Zunpretty=mir trait_monomorphization.rs
// WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
fn <impl at trait_monomorphization.rs:17:1: 21:2>::test_trait_func(_1: std::option::Option<i32>) -> std::option::Option<i32> {
let mut _0: std::option::Option<i32>; // return place in scope 0 at trait_monomorphization.rs:18:31: 18:35
bb0: {
_0 = _1; // bb0[0]: scope 0 at trait_monomorphization.rs:19:5: 19:9
return; // bb0[1]: scope 0 at trait_monomorphization.rs:20:4: 20:4
}
}
fn generic_trait_func(_1: T) -> T {
let mut _0: T; // return place in scope 0 at trait_monomorphization.rs:7:50: 7:51
let mut _2: T; // in scope 0 at trait_monomorphization.rs:8:3: 8:4
bb0: {
StorageLive(_2); // bb0[0]: scope 0 at trait_monomorphization.rs:8:3: 8:4
_2 = move _1; // bb0[1]: scope 0 at trait_monomorphization.rs:8:3: 8:4
_0 = const <T as TestTrait>::test_trait_func(move _2) -> bb1; // bb0[2]: scope 0 at trait_monomorphization.rs:8:3: 8:22
// ty::Const
// + ty: fn(T) -> T {<T as TestTrait>::test_trait_func}
// + val: Scalar(<ZST>)
// mir::Constant
// + span: trait_monomorphization.rs:8:5: 8:20
// + ty: fn(T) -> T {<T as TestTrait>::test_trait_func}
// + literal: Const { ty: fn(T) -> T {<T as TestTrait>::test_trait_func}, val: Scalar(<ZST>) }
}
bb1: {
StorageDead(_2); // bb1[0]: scope 0 at trait_monomorphization.rs:8:21: 8:22
return; // bb1[1]: scope 0 at trait_monomorphization.rs:9:2: 9:2
}
}
fn <impl at trait_monomorphization.rs:11:1: 15:2>::test_trait_func(_1: i32) -> i32 {
let mut _0: i32; // return place in scope 0 at trait_monomorphization.rs:12:31: 12:35
bb0: {
_0 = _1; // bb0[0]: scope 0 at trait_monomorphization.rs:13:5: 13:9
return; // bb0[1]: scope 0 at trait_monomorphization.rs:14:4: 14:4
}
}
fn test_func1() -> i32 {
let mut _0: i32; // return place in scope 0 at trait_monomorphization.rs:23:24: 23:27
bb0: {
_0 = const generic_trait_func::<i32>(const 0i32) -> bb1; // bb0[0]: scope 0 at trait_monomorphization.rs:24:3: 24:24
// ty::Const
// + ty: fn(i32) -> i32 {generic_trait_func::<i32>}
// + val: Scalar(<ZST>)
// mir::Constant
// + span: trait_monomorphization.rs:24:3: 24:21
// + ty: fn(i32) -> i32 {generic_trait_func::<i32>}
// + literal: Const { ty: fn(i32) -> i32 {generic_trait_func::<i32>}, val: Scalar(<ZST>) }
// ty::Const
// + ty: i32
// + val: Scalar(0x00000000)
// mir::Constant
// + span: trait_monomorphization.rs:24:22: 24:23
// + ty: i32
// + literal: Const { ty: i32, val: Scalar(0x00000000) }
}
bb1: {
return; // bb1[0]: scope 0 at trait_monomorphization.rs:25:2: 25:2
}
}
fn test_func3() -> std::option::Option<i32> {
let mut _0: std::option::Option<i32>; // return place in scope 0 at trait_monomorphization.rs:31:24: 31:35
let mut _1: std::option::Option<i32>; // in scope 0 at trait_monomorphization.rs:32:22: 32:26
bb0: {
StorageLive(_1); // bb0[0]: scope 0 at trait_monomorphization.rs:32:22: 32:26
discriminant(_1) = 0; // bb0[1]: scope 0 at trait_monomorphization.rs:32:22: 32:26
_0 = const generic_trait_func::<std::option::Option<i32>>(move _1) -> bb1; // bb0[2]: scope 0 at trait_monomorphization.rs:32:3: 32:27
// ty::Const
// + ty: fn(std::option::Option<i32>) -> std::option::Option<i32> {generic_trait_func::<std::option::Option<i32>>}
// + val: Scalar(<ZST>)
// mir::Constant
// + span: trait_monomorphization.rs:32:3: 32:21
// + ty: fn(std::option::Option<i32>) -> std::option::Option<i32> {generic_trait_func::<std::option::Option<i32>>}
// + literal: Const { ty: fn(std::option::Option<i32>) -> std::option::Option<i32> {generic_trait_func::<std::option::Option<i32>>}, val: Scalar(<ZST>) }
}
bb1: {
StorageDead(_1); // bb1[0]: scope 0 at trait_monomorphization.rs:32:26: 32:27
return; // bb1[1]: scope 0 at trait_monomorphization.rs:33:2: 33:2
}
}
fn test_func2() -> i32 {
let mut _0: i32; // return place in scope 0 at trait_monomorphization.rs:27:24: 27:27
bb0: {
_0 = const generic_trait_func::<i32>(const 333i32) -> bb1; // bb0[0]: scope 0 at trait_monomorphization.rs:28:3: 28:26
// ty::Const
// + ty: fn(i32) -> i32 {generic_trait_func::<i32>}
// + val: Scalar(<ZST>)
// mir::Constant
// + span: trait_monomorphization.rs:28:3: 28:21
// + ty: fn(i32) -> i32 {generic_trait_func::<i32>}
// + literal: Const { ty: fn(i32) -> i32 {generic_trait_func::<i32>}, val: Scalar(<ZST>) }
// ty::Const
// + ty: i32
// + val: Scalar(0x0000014d)
// mir::Constant
// + span: trait_monomorphization.rs:28:22: 28:25
// + ty: i32
// + literal: Const { ty: i32, val: Scalar(0x0000014d) }
}
bb1: {
return; // bb1[0]: scope 0 at trait_monomorphization.rs:29:2: 29:2
}
}
</pre>
<p>トレイトのメソッド呼び出しが, <tt class="docutils literal"><T as <span class="pre">Trait>::method</span></tt> みたいな形に変わり,境界条件はなくなっている. LLVM IR も見てみる:</p>
<pre class="literal-block">
$ rustc --crate-type=lib --emit=llvm-ir trait_monomorphization.rs
$ cat trait_monomorphization.ll
...
; trait_monomorphization::generic_trait_func
; Function Attrs: uwtable
define { i32, i32 } @_ZN22trait_monomorphization18generic_trait_func17h2353f770a11f3463E(i32 %x.0, i32 %x.1) unnamed_addr #0 {
start:
; call <core::option::Option<i32> as trait_monomorphization::TestTrait>::test_trait_func
%0 = call { i32, i32 } @"_ZN85_$LT$core..option..Option$LT$i32$GT$$u20$as$u20$trait_monomorphization..TestTrait$GT$15test_trait_func17h91469f85fa74f82cE"(i32 %x.0, i32 %x.1)
%1 = extractvalue { i32, i32 } %0, 0
%2 = extractvalue { i32, i32 } %0, 1
br label %bb1
bb1: ; preds = %start
%3 = insertvalue { i32, i32 } undef, i32 %1, 0
%4 = insertvalue { i32, i32 } %3, i32 %2, 1
ret { i32, i32 } %4
}
; trait_monomorphization::generic_trait_func
; Function Attrs: uwtable
define i32 @_ZN22trait_monomorphization18generic_trait_func17h888a1bef68f0d18bE(i32 %x) unnamed_addr #0 {
start:
; call <i32 as trait_monomorphization::TestTrait>::test_trait_func
%0 = call i32 @"_ZN57_$LT$i32$u20$as$u20$trait_monomorphization..TestTrait$GT$15test_trait_func17hc700a3de885bafa4E"(i32 %x)
br label %bb1
bb1: ; preds = %start
ret i32 %0
}
; <i32 as trait_monomorphization::TestTrait>::test_trait_func
; Function Attrs: uwtable
define i32 @"_ZN57_$LT$i32$u20$as$u20$trait_monomorphization..TestTrait$GT$15test_trait_func17hc700a3de885bafa4E"(i32 %self) unnamed_addr #0 {
start:
ret i32 %self
}
; <core::option::Option<i32> as trait_monomorphization::TestTrait>::test_trait_func
; Function Attrs: uwtable
define { i32, i32 } @"_ZN85_$LT$core..option..Option$LT$i32$GT$$u20$as$u20$trait_monomorphization..TestTrait$GT$15test_trait_func17h91469f85fa74f82cE"(i32 %self.0, i32 %self.1) unnamed_addr #0 {
start:
%0 = insertvalue { i32, i32 } undef, i32 %self.0, 0
%1 = insertvalue { i32, i32 } %0, i32 %self.1, 1
ret { i32, i32 } %1
}
; trait_monomorphization::test_func1
; Function Attrs: uwtable
define i32 @_ZN22trait_monomorphization10test_func117h34f6be1b1f5ee768E() unnamed_addr #0 {
start:
; call trait_monomorphization::generic_trait_func
%0 = call i32 @_ZN22trait_monomorphization18generic_trait_func17h888a1bef68f0d18bE(i32 0)
br label %bb1
bb1: ; preds = %start
ret i32 %0
}
; trait_monomorphization::test_func2
; Function Attrs: uwtable
define i32 @_ZN22trait_monomorphization10test_func217h4d629592fd7a0d2cE() unnamed_addr #0 {
start:
; call trait_monomorphization::generic_trait_func
%0 = call i32 @_ZN22trait_monomorphization18generic_trait_func17h888a1bef68f0d18bE(i32 333)
br label %bb1
bb1: ; preds = %start
ret i32 %0
}
; trait_monomorphization::test_func3
; Function Attrs: uwtable
define { i32, i32 } @_ZN22trait_monomorphization10test_func317ha2174098ce8095a3E() unnamed_addr #0 {
start:
%_1 = alloca { i32, i32 }, align 4
%0 = bitcast { i32, i32 }* %_1 to i32*
store i32 0, i32* %0, align 4
%1 = getelementptr inbounds { i32, i32 }, { i32, i32 }* %_1, i32 0, i32 0
%2 = load i32, i32* %1, align 4, !range !0
%3 = getelementptr inbounds { i32, i32 }, { i32, i32 }* %_1, i32 0, i32 1
%4 = load i32, i32* %3, align 4
; call trait_monomorphization::generic_trait_func
%5 = call { i32, i32 } @_ZN22trait_monomorphization18generic_trait_func17h2353f770a11f3463E(i32 %2, i32 %4)
%6 = extractvalue { i32, i32 } %5, 0
%7 = extractvalue { i32, i32 } %5, 1
br label %bb1
bb1: ; preds = %start
%8 = insertvalue { i32, i32 } undef, i32 %6, 0
%9 = insertvalue { i32, i32 } %8, i32 %7, 1
ret { i32, i32 } %9
}
...
</pre>
<p>やはり,普通のジェネリック関数と同じで,型ごとに特殊化されたコードが生成され,メソッドの実装もそれぞれ埋め込まれるっぽい.なお,表示が同じになるのでやらないけど,メタデータに, <tt class="docutils literal">generic_func</tt> の時と同じように <tt class="docutils literal">generic_trait_func</tt> の MIR コードも埋め込まれる.</p>
</div>
<div class="section" id="auto-id-7">
<h2>まとめ<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで, Rust のジェネリック関数は基本,関数が使われる場所を解析して,その場所の型ごとに特殊化したコードを生成しそれを使うようにする.ただ,パブリックなジェネリック関数はそのコード情報を crate に埋め込む必要があるので,メタデータに MIR コードとして入れておく.これはトレイトによる境界条件があっても変わらない,という感じっぽい.基本 C++ のテンプレートと同じで,ソース中にそのまま書ける感じかな.</p>
<p><tt class="docutils literal">rustc</tt> の解読,辛かったけど,色々情報を手に入れた.結構 <tt class="docutils literal">rustc</tt> で情報を見れるの良さそう.後, <tt class="docutils literal">rustup</tt> をそのままビルドしたコードに使えるのもいいっすね.</p>
<table class="docutils footnote" frame="void" id="mir-based-borrow-check" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>元々は HIR で借用検査 (borrow check) を行なっていたっぽいが, Rust 2018 で入った NLL (non-lexical lifetime) の為に MIR でやるようにしたっぽい.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="list-crate-metadata-usecase" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[2]</a></td><td>正直,何に使うかはよく分かってない.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/06/rust-generics-inside.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/06/rust-generics-inside.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>graded monad から monad への埋め込み2019-06-13T06:37:51+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-06-13:/blog/posts/2019/06/graded-monad-to-monad/<p>graded monad から monad への埋め込みについて,考えたので,その覚書.</p>
<div class="section" id="monad">
<h2>エフェクトシステムを monad で近似する<a class="headerlink" href="#monad" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>エフェクトシステムに …</p></div><p>graded monad から monad への埋め込みについて,考えたので,その覚書.</p>
<div class="section" id="monad">
<h2>エフェクトシステムを monad で近似する<a class="headerlink" href="#monad" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>エフェクトシステムによって,静的型情報をより詳細にできるわけだが,実行機械を作る時にはこのエフェクト情報を特に使わない実行方法が得られる場合が多い.もし, graded monad による言語を monad による言語に近似できれば, graded monad 用の実行方法をわざわざ作らなくても, monad の実行方法を流用できる.</p>
<p>では,ある graded monad が与えられた時にそいつによる意味論をうまく近似するような monad が作れないだろうかというので,以下のようなことが考えられる.</p>
</div>
<div class="section" id="auto-id-1">
<h2>monad への埋め込み<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>monoidal category <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>E</mi><mo separator="true">,</mo><mo>⋅</mo><mo separator="true">,</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(E, \cdot, 1)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">⋅</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span> において,終対象 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>E</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">F \in |E|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord">∣</span></span></span></span></span> が存在するとする.</p>
<p>graded monad <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>T</mi><mo>:</mo><mi>E</mi><mo>→</mo><mo stretchy="false">[</mo><mi>C</mi><mo separator="true">,</mo><mi>C</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>η</mi><mo>:</mo><mrow><mi mathvariant="normal">I</mi><mi mathvariant="normal">d</mi></mrow><mo>⇒</mo><mi>T</mi><mn>1</mn><mo separator="true">,</mo><mi>μ</mi><mo>:</mo><mi>T</mi><mo>−</mo><mo separator="true">;</mo><mi>T</mi><mo>−</mo><mo>⇒</mo><mi>T</mi><mo stretchy="false">(</mo><mo>−</mo><mo>⋅</mo><mo>−</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(T: E \to [C, C], \eta: \mathrm{Id} \Rightarrow T 1, \mu: T - ; T - \Rightarrow T (- \cdot -)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">Id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">μ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">−</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mclose">)</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mover accent="true"><mi>T</mi><mo>^</mo></mover><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi><mo separator="true">,</mo><mover accent="true"><mi>η</mi><mo>^</mo></mover><mo>:</mo><mrow><mi mathvariant="normal">I</mi><mi mathvariant="normal">d</mi></mrow><mo>⇒</mo><mover accent="true"><mi>T</mi><mo>^</mo></mover><mo separator="true">,</mo><mover accent="true"><mi>μ</mi><mo>^</mo></mover><mo>:</mo><msup><mover accent="true"><mi>T</mi><mo>^</mo></mover><mn>2</mn></msup><mo>⇒</mo><mi>T</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(\hat{T}: C \to C, \hat{\eta}: \mathrm{Id} \Rightarrow \hat{T}, \hat{\mu}: \hat{T}^2 \Rightarrow T)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1968em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1944em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">Id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1412em;vertical-align:-0.1944em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">μ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9468em;"></span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mclose">)</span></span></span></span></span> を次のように与える.</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>T</mi><mo>^</mo></mover><mo>=</mo><mi>T</mi><mi>F</mi></mrow><annotation encoding="application/x-tex">\hat{T} = T F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9468em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">TF</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mover accent="true"><mi>η</mi><mo>^</mo></mover><mi>A</mi></msub><mo>=</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msub><mi>η</mi><mi>A</mi></msub></mpadded></mover><mi>T</mi><mn>1</mn><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi>T</mi><mo stretchy="false">(</mo><mn>1</mn><mo>→</mo><mi>F</mi><mo stretchy="false">)</mo></mrow></mpadded></mover><mover accent="true"><mi>T</mi><mo>^</mo></mover><mi>A</mi></mrow><annotation encoding="application/x-tex">\hat{\eta}_A = A \xrightarrow{\eta_A} T 1 A \xrightarrow{T (1 \to F)} \hat{T} A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1944em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3567em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1433em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.158em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.147em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span><span class="mopen mtight">(</span><span class="mord mtight">1</span><span class="mrel mtight">→</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mclose mtight">)</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9468em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mord mathnormal">A</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mover accent="true"><mi>μ</mi><mo>^</mo></mover><mi>A</mi></msub><mo>=</mo><msup><mover accent="true"><mi>T</mi><mo>^</mo></mover><mn>2</mn></msup><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><msub><mi>μ</mi><mrow><mi>F</mi><mo separator="true">,</mo><mi>F</mi></mrow></msub></mpadded></mover><mi>T</mi><mo stretchy="false">(</mo><mi>F</mi><mo>⋅</mo><mi>F</mi><mo stretchy="false">)</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>F</mi><mo>⋅</mo><mi>F</mi><mo>→</mo><mi>F</mi><mo stretchy="false">)</mo></mrow></mpadded></mover><mover accent="true"><mi>T</mi><mo>^</mo></mover><mi>A</mi></mrow><annotation encoding="application/x-tex">\hat{\mu}_A = \hat{T}^2 A \xrightarrow{\mu_{F,F}} T (F \cdot F) A \xrightarrow{T (F \cdot F \to F)} \hat{T} A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">μ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9578em;vertical-align:-0.011em;"></span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">μ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3567em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2822em;"><span></span></span></span></span></span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.397em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mclose">)</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.147em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mbin mtight">⋅</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mrel mtight">→</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span><span class="mclose mtight">)</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9468em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mord mathnormal">A</span></span></span></span></span></li>
</ul>
<p>こいつは, monad になる.規則を満たすかは,次のように確認できる.</p>
<img alt="monad の identity について,計算している図式." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-to-monad/graded-monad-to-monad/monad-coherence-identity.png"/>
<p>こちらは, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mover accent="true"><mi>η</mi><mo>^</mo></mover><mover accent="true"><mi>T</mi><mo>^</mo></mover></msub><mo separator="true">;</mo><mover accent="true"><mi>μ</mi><mo>^</mo></mover><mo>=</mo><mover accent="true"><mi>T</mi><mo>^</mo></mover><mover accent="true"><mi>η</mi><mo>^</mo></mover><mo separator="true">;</mo><mover accent="true"><mi>μ</mi><mo>^</mo></mover><mo>=</mo><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow></mrow><annotation encoding="application/x-tex">\hat{\eta}_{\hat{T}}; \hat{\mu} = \hat{T} \hat{\eta}; \hat{\mu} = \mathrm{id}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0124em;vertical-align:-0.3179em;"></span><span class="mord"><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1944em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3821em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord accent mtight"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-2.7em;"><span class="pstrut" style="height:2.7em;"></span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span><span style="top:-2.9523em;"><span class="pstrut" style="height:2.7em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord mtight">^</span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3179em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">μ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1412em;vertical-align:-0.1944em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1944em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">μ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">id</span></span></span></span></span></span> を計算したやつ.</p>
<img alt="monad の associativity について,計算している図式." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-to-monad/graded-monad-to-monad/monad-coherence-assoc.png"/>
<p>こちらは, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mover accent="true"><mi>μ</mi><mo>^</mo></mover><mover accent="true"><mi>T</mi><mo>^</mo></mover></msub><mo separator="true">;</mo><mover accent="true"><mi>μ</mi><mo>^</mo></mover><mo>=</mo><mover accent="true"><mi>T</mi><mo>^</mo></mover><mover accent="true"><mi>μ</mi><mo>^</mo></mover><mo separator="true">;</mo><mover accent="true"><mi>μ</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">\hat{\mu}_{\hat{T}}; \hat{\mu} = \hat{T} \hat{\mu}; \hat{\mu}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0124em;vertical-align:-0.3179em;"></span><span class="mord"><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">μ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3821em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord accent mtight"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-2.7em;"><span class="pstrut" style="height:2.7em;"></span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span><span style="top:-2.9523em;"><span class="pstrut" style="height:2.7em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord mtight">^</span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3179em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">μ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1412em;vertical-align:-0.1944em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">μ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal">μ</span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2222em;"><span class="mord">^</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1944em;"><span></span></span></span></span></span></span></span></span></span> を計算したやつ.</p>
<p>なお, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi><mo>:</mo><mi>T</mi><mo>−</mo><mo separator="true">;</mo><mi>T</mi><mo>−</mo><mo>⇒</mo><mi>T</mi><mo stretchy="false">(</mo><mo>−</mo><mo>⋅</mo><mo>−</mo><mo stretchy="false">)</mo><mo>:</mo><mi>E</mi><mo>×</mo><mi>E</mi><mo>→</mo><mo stretchy="false">[</mo><mi>C</mi><mo separator="true">,</mo><mi>C</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">\mu: T -; T - \Rightarrow T (- \cdot -): E \times E \to [C, C]</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">μ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">−</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">]</span></span></span></span></span> は自然変換なので,以下を満たし,</p>
<img alt="(T(e1 -> d1); T(e2 -> d2)); \mu^{d1,d2} = \mu^{e1,e2}; T(e1 \cdot e2 -> d1 \cdot d2)" class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-to-monad/graded-monad-to-monad/lax-monoidal-functor-naturality.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi></mrow><annotation encoding="application/x-tex">F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span></span> は終対象なので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>f</mi></mpadded></mover><mi>F</mi><mo>⋅</mo><mi>F</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>g</mi></mpadded></mover><mi>F</mi><mo>=</mo><msub><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mi>F</mi></msub></mrow><annotation encoding="application/x-tex">F \xrightarrow{f} F \cdot F \xrightarrow{g} F = \mathrm{id}_F</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1191em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9344em;vertical-align:-0.011em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">id</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> なことに注意.</p>
<p>そして,自然変換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>ϵ</mi><mo>→</mo><mi>F</mi><mo stretchy="false">)</mo><mo>:</mo><mi>T</mi><mo stretchy="false">(</mo><mi>ϵ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mover accent="true"><mi>T</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">T(\epsilon \to F): T(\epsilon) \Rightarrow \hat{T}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9468em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span></span></span></span></span> が存在する.</p>
<p>preordered monoid の終対象とは, preorder での最大元に当たる.なのでこの埋め込みは,エフェクトシステム的な直感にもマッチしていて,エフェクトシステムがエフェクトの見積もりを細かくして型に情報として載せるものだったわけだけど,その細かく見積もった情報を実行時に使わないで,最大のエフェクトで動作だけ近似するというわけだ.</p>
</div>
<div class="section" id="auto-id-2">
<h2>埋め込みによる意味論の保存<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>もちろんこの埋め込みが, graded monadic な意味論を monadic な意味論にうまく近似できなければ意味がない.なので,それを確かめてみる.近似できるとは,つまり以下のものが成り立つということだ.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>⊢</mo><mi>e</mi><mo>:</mo><mi>T</mi><mi>ϵ</mi><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><msub><mi>i</mi><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow></msub><mo>=</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>⊢</mo><mi>e</mi><mo>:</mo><mover accent="true"><mi>T</mi><mo>^</mo></mover><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">
⟦x: \tau_1 \vdash e: T \epsilon \tau_2⟧; i_{⟦\tau_2⟧} = ⟦x: \tau_1 \vdash e: \hat{T} \tau_2⟧
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">i</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight"><span class="mopen mtight">[</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mopen mtight">[</span></span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.1132em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight"><span class="mclose mtight">]</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mclose mtight">]</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1968em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></div>
<p>左側が graded monadic な意味論,右側が monadic な意味論になる.ここで, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo>:</mo><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>e</mi><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo>⇒</mo><mover accent="true"><mi>T</mi><mo>^</mo></mover></mrow><annotation encoding="application/x-tex">i: T ⟦e⟧_{\mathcal{E}} \Rightarrow \hat{T}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">e</span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9468em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span></span></span></span></span> は埋め込み <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><mi>ϵ</mi><mo>→</mo><mi>F</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T(\epsilon \to F)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mclose">)</span></span></span></span></span> になる. <a class="reference external" href="../graded-monad-and-effects/#lax-monoidal-functor">以前の記事</a> で上げた構文要素それぞれで,帰納法を回してこれが一致することを示してみる.なお, effect を発生させる関数は graded monad での意味論と monad での意味論で解釈が異なる.なので,こいつらについては,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>f</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>ϵ</mi></mpadded></mover><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><msub><mi>i</mi><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow></msub><mo>=</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>f</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>→</mo><mover accent="true"><mi>T</mi><mo>^</mo></mover><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">
⟦f: \tau_1 \xrightarrow{\epsilon} \tau_2⟧; i_{⟦\tau_2⟧} = ⟦f: \tau_1 \to \hat{T} \tau_2⟧
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0734em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">i</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight"><span class="mopen mtight">[</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mopen mtight">[</span></span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.1132em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight"><span class="mclose mtight">]</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mclose mtight">]</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1968em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1667em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></div>
<p>が成り立つという仮定を置く.この下で,以下のように帰納法を用いて示すことができる.</p>
<dl class="docutils">
<dt>lift</dt>
<dd><img alt="lift 構文についてのチェック" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-to-monad/graded-monad-to-monad/embed-correct-lift.png"/>
</dd>
<dt>effectful app</dt>
<dd><img alt="effectful app 構文についてのチェック" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-to-monad/graded-monad-to-monad/embed-correct-effectful-app.png"/>
</dd>
<dt>let</dt>
<dd><img alt="let 構文についてのチェック" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-to-monad/graded-monad-to-monad/embed-correct-let.png"/>
</dd>
<dt>cast</dt>
<dd><img alt="cast 構文についてのチェック" class="first last align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-to-monad/graded-monad-to-monad/embed-correct-cast.png"/>
</dd>
</dl>
<p>ちゃんと成り立ってるっぽい.</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>この埋め込み以外にも graded monad からその近似としての monad を作る方法はありそう.一般的には, graded monad が与えられた時,いい感じの性質を満たす monad を持ってこれればそいつでいい感じに近似できるよみたいな研究があるっぽい.この手法は, graded monad をプログラミングツールとして使う場合も役に立ちそう.</p>
<p>こちらからは以上です.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/06/graded-monad-to-monad.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/06/graded-monad-to-monad.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Scala (Dotty) での Graded Monad によるメタ言語の実装2019-06-07T13:33:29+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-06-07:/blog/posts/2019/06/graded-monad-in-scala/<p>Graded Monad のメタ言語,普通にプログラミング言語で実装できそうやなって思って,ちょっとやってみることにした.で,前ね …</p><p>Graded Monad のメタ言語,普通にプログラミング言語で実装できそうやなって思って,ちょっとやってみることにした.で,前ねこはるさんが extensible effects に Dotty の union types 使う話してたの思い出して,それと同じ感じで powerset による preordered monoid に対する graded monad ぐらいなら実装できるんじゃねと思ったので, Dotty のお試しがてら実装してみることにした.</p>
<p>Dotty のお試しという要素が強いし, Scala 弱者なので,それほど真面目に実装してない.なんか興味ある方いたら,適当にフォークして勝手に自分で考えたことにしてくれ.なお書いたコードは, <a class="reference external" href="https://github.com/mizunashi-mana/graded-monad-in-scala">https://github.com/mizunashi-mana/graded-monad-in-scala</a> に上げた.</p>
<div class="section" id="dotty">
<h2>Dotty のインストール<a class="headerlink" href="#dotty" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Dotty はいつ出るか分からない, Scala の次期バージョンコンパイラ.現状の Scala の色々不便なとこが変わったり,型システムがより強力になったりするらしい.公式サイトは, <a class="reference external" href="https://dotty.epfl.ch/">https://dotty.epfl.ch/</a> .お試し利用がかなり気軽にできて公式サイトにやり方が載ってる.</p>
<p>macOS の場合は, Homebrew で,</p>
<pre class="literal-block">
brew install lampepfl/brew/dotty
</pre>
<p>すると入る.なお, <tt class="docutils literal">sbt</tt> の場合は,</p>
<pre class="literal-block">
sbt new lampepfl/dotty.g8
</pre>
<p>とすると, Dotty 用のプロジェクトが作られる.こんだけ.強い.</p>
</div>
<div class="section" id="graded-monad">
<h2>Graded Monad を定義する<a class="headerlink" href="#graded-monad" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Dotty には union type という型があり,型 <tt class="docutils literal">X</tt> , <tt class="docutils literal">Y</tt> に対して <tt class="docutils literal">X | Y</tt> と表記される.それぞれ,</p>
<ul class="simple">
<li><tt class="docutils literal">X <: (X | Y)</tt></li>
<li><tt class="docutils literal">Y <: (X | Y)</tt></li>
<li><tt class="docutils literal">X <: B</tt> かつ <tt class="docutils literal">Y <: B</tt> ならば <tt class="docutils literal">(X | Y) <: B</tt></li>
<li><tt class="docutils literal">(X | Y) =:= (Y | X)</tt></li>
<li><tt class="docutils literal">(X | (Y | Z)) =:= ((X | Y) | Z)</tt></li>
</ul>
<p>という関係が成り立つようになっている.強い.後,こいつ, <tt class="docutils literal">Nothing</tt> が単位元になる.</p>
<ul class="simple">
<li><tt class="docutils literal">(X | Nothing) =:= (Nothing | X) =:= X</tt></li>
</ul>
<p>いや強すぎるやろ.ほんまかって感じだが.</p>
<p>この型を使って, preordered monoid <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mo stretchy="false">{</mo><mtext mathvariant="monospace">X</mtext><mo>∣</mo><mrow><mtext mathvariant="monospace">X</mtext><mtext> </mtext><mtext mathvariant="monospace"><:</mtext><mtext> </mtext><mtext mathvariant="monospace">B</mtext></mrow><mo stretchy="false">}</mo><mo separator="true">,</mo><mtext mathvariant="monospace"><:</mtext><mo separator="true">,</mo><mtext mathvariant="monospace">|</mtext><mo separator="true">,</mo><mtext mathvariant="monospace">Nothing</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(\{\text{\tt X} \mid \text{\tt X <: B}\}, \text{\tt <:}, \text{\tt |}, \text{\tt Nothing})</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">({</span><span class="mord text"><span class="mord"><span class="mord mathtt">X</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">X <: B</span></span></span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt"><:</span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">|</span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">Nothing</span></span></span><span class="mclose">)</span></span></span></span></span> についての graded monad を, <tt class="docutils literal">GradedMonad</tt> として定義することにする.とりあえず,そのまんま以下の感じで書いた:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">trait</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">]]</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">self</span><span class="w"> </span><span class="o">=></span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">pfunctor</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">]:</span><span class="w"> </span><span class="nc">Functor</span><span class="p">[[</span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedUpcast</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedPure</span><span class="p">[</span><span class="nc">X</span><span class="p">](</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="p">):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">Nothing</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedFlatten</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedFlatMap</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">])(</span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="n">gradedFlatten</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">](</span><span class="n">pfunctor</span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="n">m</span><span class="p">)(</span><span class="n">f</span><span class="p">))</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<ul class="simple">
<li><tt class="docutils literal">pfunctor</tt> と <tt class="docutils literal">gradedUpcast</tt> が関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>:</mo><mi>E</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">T: E \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
<li><tt class="docutils literal">gradedPure</tt> が自然変換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>η</mi><mo>:</mo><mrow><mi mathvariant="normal">I</mi><mi mathvariant="normal">d</mi></mrow><mo>⇒</mo><mi>T</mi><mn>1</mn></mrow><annotation encoding="application/x-tex">\eta: \mathrm{Id} \Rightarrow T 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">Id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span></span></span></span></span></li>
<li><tt class="docutils literal">gradedFlatten</tt> が自然変換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi><mo>:</mo><mi>T</mi><mo>−</mo><mo lspace="0.22em" rspace="0.22em">⊗</mo><mi>T</mi><mo>−</mo><mo>⇒</mo><mi>T</mi><mo stretchy="false">(</mo><mo>−</mo><mo>⋅</mo><mo>−</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mu: T - \mathbin{\otimes} T - \Rightarrow T (- \cdot -)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">μ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">⊗</span></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>に,それぞれ対応する.後, implicit 系の API も整備しておく:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">object</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">]](</span><span class="k">implicit</span><span class="w"> </span><span class="n">tc</span><span class="p">:</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">]):</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedPure</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">],</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="p">)(</span><span class="k">implicit</span><span class="w"> </span><span class="n">tc</span><span class="p">:</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">Nothing</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">gradedPure</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nc">ToGradedMonadOps</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">final</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">toGradedMonadOps</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">],</span><span class="w"> </span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span>
<span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">tex</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="w"> </span><span class="p">)(</span><span class="k">implicit</span><span class="w"> </span><span class="n">tc</span><span class="p">:</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">map</span><span class="p">[</span><span class="nc">Y</span><span class="p">](</span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">Y</span><span class="p">):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">pfunctor</span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="n">tex</span><span class="p">)(</span><span class="n">f</span><span class="p">)</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">flatMap</span><span class="p">[</span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">](</span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">gradedFlatMap</span><span class="p">(</span><span class="n">tex</span><span class="p">)(</span><span class="n">f</span><span class="p">)</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">withFilter</span><span class="p">(</span><span class="n">p</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">Boolean</span><span class="p">):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">pfunctor</span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="n">tex</span><span class="p">)(</span>
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">p</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="k">then</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">RuntimeException</span><span class="p">(</span><span class="s">"Pattern match failed: GradedMonad.withFilter"</span><span class="p">)</span>
<span class="w"> </span><span class="p">)</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">foreach</span><span class="p">[</span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">](</span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">gradedFlatMap</span><span class="p">(</span><span class="n">tex</span><span class="p">)(</span><span class="n">f</span><span class="p">)</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">upcast</span><span class="p">[</span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">]:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">gradedUpcast</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">tex</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">final</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">toGradedMonadFlattenOps</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">],</span><span class="w"> </span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span>
<span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">teex</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span>
<span class="w"> </span><span class="p">)(</span><span class="k">implicit</span><span class="w"> </span><span class="n">tc</span><span class="p">:</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">flatten</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">gradedFlatten</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">teex</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">GradedMonad.gradedPure</tt> はインスタンスを自動で探してくれる版, <tt class="docutils literal">toGradedMonadOps</tt> は <tt class="docutils literal">for</tt> や <tt class="docutils literal">for yield</tt> 系統の implicit conversion を提供してくれる.その他も幾つか書いたけど,使うのは大体その辺だけになった.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">v1</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">program1</span>
<span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">program2</span><span class="p">(</span><span class="n">v1</span><span class="p">)</span>
<span class="w"> </span><span class="n">v2</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">program3</span><span class="p">(</span><span class="n">v2</span><span class="p">)</span>
<span class="p">}</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">.</span><span class="n">gradedPure</span><span class="p">((</span><span class="n">v1</span><span class="p">,</span><span class="w"> </span><span class="n">v2</span><span class="p">))</span>
</pre></div></td></tr></table></div>
<p>または,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">for</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">v1</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">program1</span>
<span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">program2</span><span class="p">(</span><span class="n">v1</span><span class="p">)</span>
<span class="w"> </span><span class="n">v2</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="n">program3</span><span class="p">(</span><span class="n">v2</span><span class="p">)</span>
<span class="p">}</span><span class="w"> </span><span class="k">yield</span><span class="w"> </span><span class="p">(</span><span class="n">v1</span><span class="p">,</span><span class="w"> </span><span class="n">v2</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>みたいにコードを書ける.後,こいつが満たさなきゃいけない性質の検査コードも書いておいた:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">trait</span><span class="w"> </span><span class="nc">GradedMonadLaws</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="n">_</span><span class="p">]]</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">T</span><span class="p">:</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedMonadIdentity</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]):</span><span class="w"> </span><span class="nc">IsEq</span><span class="p">[</span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="n">m</span><span class="p">.</span><span class="n">upcast</span><span class="w"> </span><span class="o"><-></span><span class="w"> </span><span class="n">m</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedMonadComposition</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E3</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]):</span><span class="w"> </span><span class="nc">IsEq</span><span class="p">[</span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E3</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="n">m</span><span class="p">.</span><span class="n">upcast</span><span class="p">[</span><span class="nc">E2</span><span class="p">].</span><span class="n">upcast</span><span class="p">[</span><span class="nc">E3</span><span class="p">]</span><span class="w"> </span><span class="o"><-></span><span class="w"> </span><span class="n">m</span><span class="p">.</span><span class="n">upcast</span><span class="p">[</span><span class="nc">E2</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E3</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedMonadAssociativity</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E3</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E3</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]]):</span><span class="w"> </span><span class="nc">IsEq</span><span class="p">[</span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E3</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="n">m</span><span class="p">.</span><span class="n">flatten</span><span class="p">.</span><span class="n">flatten</span><span class="w"> </span><span class="o"><-></span><span class="w"> </span><span class="n">m</span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="n">_</span><span class="p">.</span><span class="n">flatten</span><span class="p">).</span><span class="n">flatten</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedMonadLeftIdentity</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]):</span><span class="w"> </span><span class="nc">IsEq</span><span class="p">[</span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="nc">GradedMonad</span><span class="p">.</span><span class="n">gradedPure</span><span class="p">(</span><span class="n">m</span><span class="p">).</span><span class="n">flatten</span><span class="w"> </span><span class="o"><-></span><span class="w"> </span><span class="n">m</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedMonadRightIdentity</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]):</span><span class="w"> </span><span class="nc">IsEq</span><span class="p">[</span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="n">m</span><span class="p">.</span><span class="n">map</span><span class="p">(</span><span class="nc">GradedMonad</span><span class="p">.</span><span class="n">gradedPure</span><span class="p">(</span><span class="n">_</span><span class="p">)).</span><span class="n">flatten</span><span class="w"> </span><span class="o"><-></span><span class="w"> </span><span class="n">m</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">gradedMonadIdentity</tt> と <tt class="docutils literal">gradedMonadComposition</tt> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi></mrow><annotation encoding="application/x-tex">T</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span></span></span></span> が関手であることを要求してて,後のは lax monoidal functor のコヒーレンス規則になる.</p>
</div>
<div class="section" id="auto-id-1">
<h2>インスタンスを定義する<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>で,具体的にインスタンスも定義してみる.まずは, state から:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span>
<span class="normal">46</span>
<span class="normal">47</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">final</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">],</span><span class="w"> </span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="kd">val</span><span class="w"> </span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="nc">GradedStateMapping</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">ME</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">ME</span><span class="p">]):</span><span class="w"> </span><span class="p">(</span><span class="nc">X</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">ME</span><span class="p">])</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">trait</span><span class="w"> </span><span class="nc">GradedStateMapping</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">],</span><span class="w"> </span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">ME</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">ME</span><span class="p">]):</span><span class="w"> </span><span class="p">(</span><span class="nc">X</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">ME</span><span class="p">])</span>
<span class="p">}</span>
<span class="k">object</span><span class="w"> </span><span class="nc">GradedState</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedPure</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">],</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="p">)(</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="n">tc</span><span class="p">:</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedState</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span>
<span class="w"> </span><span class="p">):</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">Nothing</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">gradedPure</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nc">ToGradedStateOps</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedStateOps</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">]](</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="n">effectUpcast</span><span class="p">:</span><span class="w"> </span><span class="nc">EffectUpcast</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">]</span>
<span class="w"> </span><span class="p">):</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedState</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">pfunctor</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">]:</span><span class="w"> </span><span class="nc">Functor</span><span class="p">[[</span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">Functor</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">map</span><span class="p">[</span><span class="nc">X</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">X</span><span class="p">])(</span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">Y</span><span class="p">):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">Y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="nc">GradedStateMapping</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">ME</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">ME</span><span class="p">]):</span><span class="w"> </span><span class="p">(</span><span class="nc">Y</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">ME</span><span class="p">])</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">s2</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="w"> </span><span class="n">s2</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">})</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedUpcast</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="nc">GradedStateMapping</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">ME</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">ME</span><span class="p">]):</span><span class="w"> </span><span class="p">(</span><span class="nc">X</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">ME</span><span class="p">])</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">s2</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">effectUpcast</span><span class="p">.</span><span class="n">upcast</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">ME</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="p">](</span><span class="n">s2</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">})</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedPure</span><span class="p">[</span><span class="nc">X</span><span class="p">](</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="p">):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">Nothing</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="nc">GradedStateMapping</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">ME</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">ME</span><span class="p">]):</span><span class="w"> </span><span class="p">(</span><span class="nc">X</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">ME</span><span class="p">])</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">s</span><span class="p">)</span>
<span class="w"> </span><span class="p">})</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedFlatten</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="nc">GradedStateMapping</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">ME</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">ME</span><span class="p">]):</span><span class="w"> </span><span class="p">(</span><span class="nc">X</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">ME</span><span class="p">])</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="p">(</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="p">(</span><span class="n">m2</span><span class="p">,</span><span class="w"> </span><span class="n">s2</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">m2</span><span class="p">(</span><span class="n">s2</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">})</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>もうちょっとうまい定義方法がある気がするけど, Scala 力が足りないのでこうなった.こいつは,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mi>ϵ</mi><mo>=</mo><msub><mo>∫</mo><mrow><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∈</mo><mi>E</mi></mrow></msub><mo stretchy="false">(</mo><mo>−</mo><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><mi>ϵ</mi><mo>⋅</mo><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><msup><mo stretchy="false">)</mo><mrow><mi>S</mi><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow></msup></mrow><annotation encoding="application/x-tex">
T \epsilon = \int_{\epsilon' \in E} (- \times S(\epsilon \cdot \epsilon'))^{S \epsilon'}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2993em;vertical-align:-0.9393em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right:0.44445em;position:relative;top:-0.0011em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-0.4336em;"><span style="top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.9393em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2425em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9925em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<p>にそのまま対応する.自然数のメモリストアの例も,リテラル型を使えば表すことができて,以下のように作れる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">final</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">](</span><span class="kd">val</span><span class="w"> </span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="nc">PartialFunction</span><span class="p">[</span><span class="nc">I</span><span class="p">,</span><span class="w"> </span><span class="nc">Int</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">(</span><span class="n">ix</span><span class="p">:</span><span class="w"> </span><span class="nc">I</span><span class="p">):</span><span class="w"> </span><span class="nc">Option</span><span class="p">[</span><span class="nc">Int</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">f</span><span class="p">.</span><span class="n">lift</span><span class="p">(</span><span class="n">ix</span><span class="p">)</span>
<span class="p">}</span>
<span class="k">implicit</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">EffectUpcast</span><span class="p">[</span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">empty</span><span class="p">:</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">Nothing</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">(</span><span class="nc">Map</span><span class="p">.</span><span class="n">empty</span><span class="p">)</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">domainCast</span><span class="p">[</span><span class="nc">I1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">I2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I1</span><span class="p">]):</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">({</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">f</span><span class="p">.</span><span class="n">isDefinedAt</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="k">asInstanceOf</span><span class="p">[</span><span class="nc">I1</span><span class="p">])</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="k">asInstanceOf</span><span class="p">[</span><span class="nc">I1</span><span class="p">])</span>
<span class="w"> </span><span class="p">})</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">upcast</span><span class="p">[</span><span class="nc">I1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">I2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I1</span><span class="p">]):</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">I2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">domainCast</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">addValue</span><span class="p">[</span><span class="nc">I1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">I2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I1</span><span class="p">])(</span><span class="n">ix</span><span class="p">:</span><span class="w"> </span><span class="nc">I2</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">:</span><span class="w"> </span><span class="nc">Int</span><span class="p">):</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">I2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">(</span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">({</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">x</span><span class="p">.</span><span class="k">asInstanceOf</span><span class="p">[</span><span class="nc">I2</span><span class="p">]</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">ix</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">v</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">f</span><span class="p">.</span><span class="n">isDefinedAt</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="k">asInstanceOf</span><span class="p">[</span><span class="nc">I1</span><span class="p">])</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="k">asInstanceOf</span><span class="p">[</span><span class="nc">I1</span><span class="p">])</span>
<span class="w"> </span><span class="p">})</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="k">type</span><span class="w"> </span><span class="nc">GradedMemoryState</span><span class="p">[</span><span class="nc">I</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">[</span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">,</span><span class="w"> </span><span class="nc">I</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">getMemoryStore</span><span class="p">[</span><span class="nc">I</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">](</span><span class="n">ix</span><span class="p">:</span><span class="w"> </span><span class="nc">I</span><span class="p">):</span><span class="w"> </span><span class="nc">GradedMemoryState</span><span class="p">[</span><span class="nc">I</span><span class="p">,</span><span class="w"> </span><span class="nc">Option</span><span class="p">[</span><span class="nc">Int</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="nc">GradedStateMapping</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">I2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I2</span><span class="p">])</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w"> </span><span class="nc">MemoryStore</span><span class="p">.</span><span class="n">domainCast</span><span class="p">[</span><span class="nc">I2</span><span class="p">,</span><span class="w"> </span><span class="nc">I</span><span class="p">](</span><span class="n">s</span><span class="p">)(</span><span class="n">ix</span><span class="p">),</span>
<span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="n">upcast</span><span class="p">[</span><span class="nc">I</span><span class="p">]</span>
<span class="w"> </span><span class="p">)</span>
<span class="p">})</span>
<span class="k">def</span><span class="w"> </span><span class="nf">putMemoryStore</span><span class="p">[</span><span class="nc">I</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">](</span><span class="n">ix</span><span class="p">:</span><span class="w"> </span><span class="nc">I</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">:</span><span class="w"> </span><span class="nc">Int</span><span class="p">):</span><span class="w"> </span><span class="nc">GradedMemoryState</span><span class="p">[</span><span class="nc">I</span><span class="p">,</span><span class="w"> </span><span class="nc">Unit</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedState</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="nc">GradedStateMapping</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">apply</span><span class="p">[</span><span class="nc">I2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">Int</span><span class="p">](</span><span class="n">s</span><span class="p">:</span><span class="w"> </span><span class="nc">MemoryStore</span><span class="p">[</span><span class="nc">I2</span><span class="p">])</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w"> </span><span class="p">(),</span>
<span class="w"> </span><span class="nc">MemoryStore</span><span class="p">.</span><span class="n">addValue</span><span class="p">(</span><span class="n">s</span><span class="p">)(</span><span class="n">ix</span><span class="p">,</span><span class="w"> </span><span class="n">v</span><span class="p">)</span>
<span class="w"> </span><span class="p">)</span>
<span class="p">})</span>
</pre></div></td></tr></table></div>
<p>Int のリテラル型は, <tt class="docutils literal">1 <: Int</tt> , <tt class="docutils literal">2 <: Int</tt> という関係を満たすようになってて,こいつは今までアクセスしたインデックスが, <tt class="docutils literal">1 | 2</tt> というように型に現れるようになる.他にも,例外モナドを拡張して以下のような graded monad を作れる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">enum</span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">],</span><span class="w"> </span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="kd">val</span><span class="w"> </span><span class="n">result</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="p">)</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="kd">val</span><span class="w"> </span><span class="n">error</span><span class="p">:</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="nc">E</span><span class="p">])</span>
<span class="p">}</span>
<span class="k">object</span><span class="w"> </span><span class="nc">GradedTry</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedPure</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">],</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="p">)(</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="n">tc</span><span class="p">:</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span>
<span class="w"> </span><span class="p">):</span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">Nothing</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tc</span><span class="p">.</span><span class="n">gradedPure</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="nc">ToGradedTryOps</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedTryOps</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">[</span><span class="n">_</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">]](</span>
<span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="n">effectUpcast</span><span class="p">:</span><span class="w"> </span><span class="nc">EffectUpcast</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">]</span>
<span class="w"> </span><span class="p">):</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">GradedMonad</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">pfunctor</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">]:</span><span class="w"> </span><span class="nc">Functor</span><span class="p">[[</span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">Functor</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">[</span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">S</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">map</span><span class="p">[</span><span class="nc">X</span><span class="p">,</span><span class="w"> </span><span class="nc">Y</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">X</span><span class="p">])(</span><span class="n">f</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">Y</span><span class="p">):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">Y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedUpcast</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="n">effectUpcast</span><span class="p">.</span><span class="n">upcast</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">](</span><span class="n">e</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedPure</span><span class="p">[</span><span class="nc">X</span><span class="p">](</span><span class="n">x</span><span class="p">:</span><span class="w"> </span><span class="nc">X</span><span class="p">):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">Nothing</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">gradedFlatten</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">B</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">m</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]]):</span><span class="w"> </span><span class="nc">T</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">m2</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="n">m2</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="n">effectUpcast</span><span class="p">.</span><span class="n">upcast</span><span class="p">[</span><span class="nc">E2</span><span class="p">,</span><span class="w"> </span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">](</span><span class="n">e</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedFailure</span><span class="p">(</span><span class="n">effectUpcast</span><span class="p">.</span><span class="n">upcast</span><span class="p">[</span><span class="nc">E1</span><span class="p">,</span><span class="w"> </span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">](</span><span class="n">e</span><span class="p">))</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>こいつは,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mi>ϵ</mi><mo>=</mo><msub><mo>∫</mo><mrow><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∈</mo><mi>E</mi></mrow></msub><mi>S</mi><mo stretchy="false">(</mo><mi>ϵ</mi><mo>⋅</mo><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><mo>+</mo><mo stretchy="false">(</mo><mo>−</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
T \epsilon = \int_{\epsilon' \in E} S(\epsilon \cdot \epsilon') + (-)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2993em;vertical-align:-0.9393em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right:0.44445em;position:relative;top:-0.0011em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-0.4336em;"><span style="top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.9393em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mclose">)</span></span></span></span></span></div>
<p>に対応する.なお,現状の Dotty は, higher kinded type に対してのパターンマッチの網羅性検査があまりうまくいかないようで <a class="footnote-reference" href="#dotty-hkt-pattern-check-problem" id="auto-id-2">[1]</a> ,めっちゃ警告が出るけど気にしないでくれ.これを使うと,例外を複数種類投げる計算を管理することができて,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">sealed</span><span class="w"> </span><span class="k">abstract</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">CustomException</span>
<span class="k">final</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Exception1</span><span class="p">()</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">CustomException</span>
<span class="k">final</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Exception2</span><span class="p">()</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">CustomException</span>
<span class="k">final</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Exception3</span><span class="p">()</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">CustomException</span>
<span class="k">final</span><span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Exc</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">CustomException</span><span class="p">](</span><span class="kd">val</span><span class="w"> </span><span class="n">exc</span><span class="p">:</span><span class="w"> </span><span class="nc">E</span><span class="p">)</span>
<span class="k">implicit</span><span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="nc">Exc</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nc">EffectUpcast</span><span class="p">[</span><span class="nc">CustomException</span><span class="p">,</span><span class="w"> </span><span class="nc">Exc</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">upcast</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">CustomException</span><span class="p">,</span><span class="w"> </span><span class="nc">E2</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">CustomException</span><span class="p">](</span><span class="n">e</span><span class="p">:</span><span class="w"> </span><span class="nc">Exc</span><span class="p">[</span><span class="nc">E1</span><span class="p">]):</span><span class="w"> </span><span class="nc">Exc</span><span class="p">[</span><span class="nc">E1</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nc">E2</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">e</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">Exc</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">Exc</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
<span class="k">type</span><span class="w"> </span><span class="nc">GradedExcTry</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">CustomException</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">[</span><span class="nc">CustomException</span><span class="p">,</span><span class="w"> </span><span class="nc">Exc</span><span class="p">,</span><span class="w"> </span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">fromEither</span><span class="p">[</span><span class="nc">E</span><span class="w"> </span><span class="o"><:</span><span class="w"> </span><span class="nc">CustomException</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">](</span><span class="n">r</span><span class="p">:</span><span class="w"> </span><span class="nc">Either</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]):</span><span class="w"> </span><span class="nc">GradedExcTry</span><span class="p">[</span><span class="nc">E</span><span class="p">,</span><span class="w"> </span><span class="nc">X</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">Left</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">.</span><span class="nc">GradedFailure</span><span class="p">(</span><span class="nc">Exc</span><span class="p">(</span><span class="n">e</span><span class="p">))</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="nc">Right</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=></span><span class="w"> </span><span class="nc">GradedTry</span><span class="p">.</span><span class="nc">GradedSuccess</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>みたいな物を用意してやると, <tt class="docutils literal">Exception1</tt> を投げるプログラムと <tt class="docutils literal">Exception2</tt> を投げるプログラムを合成した時,ちゃんと <tt class="docutils literal">Exception1 | Exception2</tt> の例外を投げるプログラムにできる.</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まだやってないんだけど,モナドの時と同じようにして, freer な graded monad を考えることもできそう.こいつはうまく作れればハンドルできたりもして, Dotty で algebraic effect を再現できたりしないかなと思ってる.まあ,まだ思ってるだけだけど.時間があったらその辺も試してみたい.</p>
<p>Dotty かなり気軽に触れて良さそう. Scala 力もちょっと上がった気がする. Dotty だと union type があるから結構実装できたけど, Haskell とかだとちょっと厳しそう? あまり深く考えていない.また時間があったら試してみようと思う.</p>
<table class="docutils footnote" frame="void" id="dotty-hkt-pattern-check-problem" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><a class="reference external" href="https://github.com/lampepfl/dotty/issues/6088">https://github.com/lampepfl/dotty/issues/6088</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/06/graded-monad-in-scala.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/06/graded-monad-in-scala.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Graded Monad とエフェクト2019-06-06T07:13:18+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-06-06:/blog/posts/2019/06/graded-monad-and-effects/<p>graded monad について聞きかじって,色々調べたのでそのメモ. graded monad はエフェクトシステムの categorical semantics 作るときに使われてるらしい.エフェクトシステ …</p><p>graded monad について聞きかじって,色々調べたのでそのメモ. graded monad はエフェクトシステムの categorical semantics 作るときに使われてるらしい.エフェクトシステム勉強会でも話があったやつ.</p>
<div class="section" id="auto-id-1">
<h2>モナドとエフェクト<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まず基本的なやつから.以下の構造は一対一の対応を持つ.</p>
<dl class="docutils">
<dt>クライスリトリプル (Kleisli triple)</dt>
<dd><p class="first">圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> 上のクライスリトリプルとは,以下の要素の組 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>T</mi><mo separator="true">,</mo><mi>η</mi><mo>=</mo><msub><mo>∏</mo><mrow><mi>A</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow></msub><msub><mi>η</mi><mi>A</mi></msub><mo separator="true">,</mo><msup><mo>−</mo><mo>∗</mo></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(T, \eta = \prod_{A \in |C|} \eta_A, -^*)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∏</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="mrel mtight">∈</span><span class="mord mtight">∣</span><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span><span class="mord mtight">∣</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mbin">−</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> で,</p>
<ul class="simple">
<li>写像 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>:</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi><mo>→</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">T: |C| \to |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">A \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> に対して <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>η</mi><mi>A</mi></msub><mo>∈</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>A</mi><mo separator="true">,</mo><mi>T</mi><mi>A</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\eta_A \in \mathrm{Hom}_C(A, T A)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">A</span><span class="mclose">)</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo separator="true">,</mo><mi>B</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">A, B \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> についての, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>∈</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>A</mi><mo separator="true">,</mo><mi>T</mi><mi>B</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f \in \mathrm{Hom}_C(A, T B)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">TB</span><span class="mclose">)</span></span></span></span></span> に対する操作 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>f</mi><mo>∗</mo></msup><mo>∈</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>T</mi><mi>A</mi><mo separator="true">,</mo><mi>T</mi><mi>B</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f^* \in \mathrm{Hom}_C(T A, T B)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">TB</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>以下の条件を満たすもの</p>
<ul class="last simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">A \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>η</mi><mi>A</mi><mo>∗</mo></msubsup><mo>=</mo><mi>i</mi><msub><mi>d</mi><mrow><mi>T</mi><mi>A</mi></mrow></msub></mrow><annotation encoding="application/x-tex">\eta_A^* = id_{T A}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.964em;vertical-align:-0.2753em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-2.4247em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord mathnormal">i</span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>∈</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>A</mi><mo separator="true">,</mo><mi>T</mi><mi>B</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f \in \mathrm{Hom}_C(A, T B)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">TB</span><span class="mclose">)</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>η</mi><mi>A</mi></msub><mo separator="true">;</mo><msup><mi>f</mi><mo>∗</mo></msup><mo>=</mo><mi>f</mi></mrow><annotation encoding="application/x-tex">\eta_A; f^* = f</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>∈</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>A</mi><mo separator="true">,</mo><mi>T</mi><mi>B</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f \in \mathrm{Hom}_C(A, T B)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">TB</span><span class="mclose">)</span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>g</mi><mo>∈</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>B</mi><mo separator="true">,</mo><mi>T</mi><mi>C</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">g \in \mathrm{Hom}_C(B, T C)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">TC</span><span class="mclose">)</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>f</mi><mo>∗</mo></msup><mo separator="true">;</mo><msup><mi>g</mi><mo>∗</mo></msup><mo>=</mo><mo stretchy="false">(</mo><mi>f</mi><mo separator="true">;</mo><mi>g</mi><msup><mo stretchy="false">)</mo><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">f^*; g^* = (f; g)^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
</dd>
<dt>モナド (monad)</dt>
<dd><p class="first">圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> 上のモナドとは,以下の要素の組 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>T</mi><mo separator="true">,</mo><mi>η</mi><mo separator="true">,</mo><mi>μ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(T, \eta, \mu)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">μ</span><span class="mclose">)</span></span></span></span></span> で,</p>
<ul class="simple">
<li>関手 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">T: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
<li>自然変換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>η</mi><mo>:</mo><mrow><mi mathvariant="normal">I</mi><mi mathvariant="normal">d</mi></mrow><mo>⇒</mo><mi>T</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">\eta: \mathrm{Id} \Rightarrow T: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">Id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
<li>自然変換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi><mo>:</mo><msup><mi>T</mi><mn>2</mn></msup><mo>⇒</mo><mi>T</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">\mu: T^2 \Rightarrow T: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">μ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
</ul>
<p>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">A \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> について,以下を満たすもの</p>
<img alt="\eta_{T A}; \eta_A = T \eta_A; \eta_A" class="last align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-and-effects/graded-monad-and-effects/monad-coherence.png"/>
</dd>
</dl>
<p>対応は以下のように作る.</p>
<dl class="docutils">
<dt>クライスリトリプルからモナド</dt>
<dd><p class="first">クライスリトリプル <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>T</mi><mo separator="true">,</mo><mi>η</mi><mo separator="true">,</mo><msup><mo>−</mo><mo>∗</mo></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(T, \eta, -^*)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mbin">−</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> に対して,モナド <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msup><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><msup><mi>η</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><msup><mi>μ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(T', \eta', \mu')</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0019em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> は以下のように作る.</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>:</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi><mo>→</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi><mo separator="true">;</mo><mi>A</mi><mo>↦</mo><mi>T</mi><mi>A</mi></mrow><annotation encoding="application/x-tex">T': |C| \to |C|; A \mapsto T A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">A</span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>:</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>A</mi><mo separator="true">,</mo><mi>B</mi><mo stretchy="false">)</mo><mo>→</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><msup><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mi>A</mi><mo separator="true">,</mo><msup><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mi>B</mi><mo stretchy="false">)</mo><mo separator="true">;</mo><mi>f</mi><mo>↦</mo><mo stretchy="false">(</mo><mi>f</mi><mo separator="true">;</mo><msub><mi>η</mi><mi>B</mi></msub><msup><mo stretchy="false">)</mo><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">T': \mathrm{Hom}_C(A, B) \to \mathrm{Hom}_C(T' A, T' B); f \mapsto (f; \eta_B)^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0019em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>η</mi><mi>A</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo>=</mo><msub><mi>η</mi><mi>A</mi></msub></mrow><annotation encoding="application/x-tex">\eta'_A = \eta_A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0272em;vertical-align:-0.2753em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4247em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>μ</mi><mi>A</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo>=</mo><mo stretchy="false">(</mo><msub><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mrow><mi>T</mi><mi>A</mi></mrow></msub><msup><mo stretchy="false">)</mo><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">\mu'_A = (\mathrm{id}_{T A})^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0272em;vertical-align:-0.2753em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4247em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">id</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p class="last">これがモナドであることの証明はめんどくさいのでやらないけど,やればできる.</p>
</dd>
<dt>モナドからクライスリトリプル</dt>
<dd><p class="first">モナド <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>T</mi><mo separator="true">,</mo><mi>η</mi><mo separator="true">,</mo><mi>μ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(T, \eta, \mu)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">μ</span><span class="mclose">)</span></span></span></span></span> に対して,クライスリトリプル <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msup><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><msup><mi>η</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><msup><mo>−</mo><mo>∗</mo></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(T', \eta', -^*)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0019em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mbin">−</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> は以下のように作る.</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">;</mo><mi>A</mi><mo>↦</mo><mi>T</mi><mi>A</mi></mrow><annotation encoding="application/x-tex">T'; A \mapsto T A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.9463em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">A</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>η</mi><mi>A</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msubsup><mo>=</mo><msub><mi>η</mi><mi>A</mi></msub></mrow><annotation encoding="application/x-tex">\eta'_A = \eta_A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0272em;vertical-align:-0.2753em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4247em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>f</mi></mpadded></mover><mi>T</mi><mi>B</mi><msup><mo stretchy="false">)</mo><mo>∗</mo></msup><mo>=</mo><mo stretchy="false">(</mo><mi>T</mi><mi>f</mi><mo stretchy="false">)</mo><mo separator="true">;</mo><msub><mi>μ</mi><mi>B</mi></msub></mrow><annotation encoding="application/x-tex">(A \xrightarrow{f} T B)^* = (T f); \mu_B</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.3581em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">TB</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p class="last">こっちもクライスリトリプルであることの証明は省略する.</p>
</dd>
</dl>
<p>この作り方は,互いに同型になっていることも確かめれば分かる.というわけで,クライスリトリプルは実質モナド.モナドはコヒーレンス規則が綺麗な形をしていて分かりやすいわけだけど,クライスリトリプルの形の方がプログラム意味論を考える上では便利.</p>
<p>さてこいつらがプログラム意味論とどう関わってくるかだけど,例えば以下の構文を持つ簡単な言語に対して意味論を与えることを考えたい.考える言語は,</p>
<ul class="simple">
<li>型がある. (type)</li>
<li>型がついた変数がある. (var)</li>
<li>関数適用ができる. (app)</li>
<li>式の等価性が判定できる. (eq)</li>
</ul>
<p>みたいな感じ.だいたい次のようなものを想像してくれ.</p>
<img alt="単純な言語の構文.上で挙げた四つの構文要素の規則." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-and-effects/graded-monad-and-effects/simple-lang-syntax.png"/>
<p>で,こいつらには圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> 上のいい感じの categorical な意味論が与えられていて,</p>
<ul class="simple">
<li>型 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∈</mo><mi mathvariant="script">A</mi></mrow><annotation encoding="application/x-tex">A \in \mathcal{A}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathcal">A</span></span></span></span></span> の解釈 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>A</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">⟦A⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">A</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span> は, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">|C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> の中で与えられる.</li>
<li>関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><msub><mi>A</mi><mn>1</mn></msub><mo>→</mo><msub><mi>A</mi><mn>2</mn></msub><mo>∈</mo><mi mathvariant="script">F</mi></mrow><annotation encoding="application/x-tex">f: A_1 \to A_2 \in \mathcal{F}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathcal" style="margin-right:0.09931em;">F</span></span></span></span></span> の解釈 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>f</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">⟦f⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span> は, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>A</mi><mn>1</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">,</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>A</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{Hom}_C(⟦A_1⟧, ⟦A_2⟧)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mclose">)</span></span></span></span></span> の中で与えられる.</li>
<li>アサーション <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⊢</mo></mrow><annotation encoding="application/x-tex">\vdash</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mrel">⊢</span></span></span></span></span> は, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> の射の等価性判定に対応する.</li>
</ul>
<p>という感じになっていて,上の規則には,</p>
<ul class="simple">
<li>var: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">d</mi></mrow><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>A</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow></msub></mrow><annotation encoding="application/x-tex">\mathrm{id}_{⟦A⟧}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0496em;vertical-align:-0.3552em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">id</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight"><span class="mopen mtight">[</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mopen mtight">[</span></span><span class="mord mathnormal mtight">A</span><span class="mclose mtight"><span class="mclose mtight">]</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mclose mtight">]</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li>app: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><mi>A</mi><mo>⊢</mo><msub><mi>e</mi><mn>1</mn></msub><mo>:</mo><msub><mi>A</mi><mn>1</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>f</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">⟦x: A \vdash e_1: A_1⟧; ⟦f⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></li>
<li>eq: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>A</mi><mn>1</mn></msub><mo>⊢</mo><msub><mi>e</mi><mn>1</mn></msub><mo>:</mo><msub><mi>A</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>=</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>A</mi><mn>1</mn></msub><mo>⊢</mo><msub><mi>e</mi><mn>2</mn></msub><mo>:</mo><msub><mi>A</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">⟦x: A_1 \vdash e_1: A_2⟧ = ⟦x: A_1 \vdash e_2: A_2⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></li>
</ul>
<p>という解釈がついてると想定する.さて現実の言語では,もうちょっと高尚な要素が欲しい場合がある.例えば,計算途中で例外を投げる,状態を更新しながら計算を行うとかだ.これを,上の意味論を流用しながら組み込めないかと考えた時,クライスリトリプルが登場する.例外を例にすると,例外の集合を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi></mrow><annotation encoding="application/x-tex">E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> とした時,次のクライスリトリプル <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>T</mi><mo separator="true">,</mo><mi>η</mi><mo separator="true">,</mo><msup><mo>−</mo><mo>∗</mo></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(T, \eta, -^*)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mbin">−</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> を考える <a class="footnote-reference" href="#category-has-coproduct" id="auto-id-2">[1]</a> .</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo separator="true">;</mo><mi>A</mi><mo>↦</mo><mi>A</mi><mo>+</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">T; A \mapsto A + E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>η</mi><mi>A</mi></msub><mo>=</mo><msub><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">j</mi></mrow><mi>A</mi></msub></mrow><annotation encoding="application/x-tex">\eta_A = \mathrm{inj}_A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.912em;vertical-align:-0.2441em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">inj</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2342em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>f</mi></mpadded></mover><mi>B</mi><mo>+</mo><mi>E</mi><msup><mo stretchy="false">)</mo><mo>∗</mo></msup><mo stretchy="false">(</mo><msub><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">j</mi></mrow><mi>A</mi></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(A \xrightarrow{f} B + E)^*(\mathrm{inj}_A(x)) = f(x)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.3581em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">inj</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2342em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>A</mi><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>f</mi></mpadded></mover><mi>B</mi><mo>+</mo><mi>E</mi><msup><mo stretchy="false">)</mo><mo>∗</mo></msup><mo stretchy="false">(</mo><msub><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">j</mi></mrow><mi>E</mi></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><msub><mrow><mi mathvariant="normal">i</mi><mi mathvariant="normal">n</mi><mi mathvariant="normal">j</mi></mrow><mi>E</mi></msub><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(A \xrightarrow{f} B + E)^*(\mathrm{inj}_E(x)) = \mathrm{inj}_E(x)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.3581em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1081em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">inj</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2342em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">inj</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2342em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></span></li>
</ul>
<p>こいつを使って,次の構文を追加してさっきの意味論を拡張する.</p>
<img alt="三つの新たな構文要素の規則." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-and-effects/graded-monad-and-effects/monadic-meta-syntax.png"/>
<p>で,さっきの要素の解釈については特に変えないで,新たな要素について,</p>
<ul class="simple">
<li>type lift: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>τ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">T ⟦\tau⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></li>
<li>lift: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>⊢</mo><mi>e</mi><mo>:</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><msub><mi>η</mi><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow></msub></mrow><annotation encoding="application/x-tex">⟦x: \tau_1 \vdash e: \tau_2⟧; \eta_{⟦\tau_2⟧}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight"><span class="mopen mtight">[</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mopen mtight">[</span></span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.1132em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight"><span class="mclose mtight">]</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mclose mtight">]</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li>let: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>⊢</mo><msub><mi>e</mi><mn>1</mn></msub><mo>:</mo><mi>T</mi><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>x</mi><mn>1</mn></msub><mo>:</mo><msub><mi>τ</mi><mn>2</mn></msub><mo>⊢</mo><msub><mi>e</mi><mn>2</mn></msub><mo>:</mo><mi>T</mi><msub><mi>τ</mi><mn>3</mn></msub><msup><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">⟦x: \tau_1 \vdash e_1: T \tau_2⟧; ⟦x_1: \tau_2 \vdash e_2: T \tau_3⟧^*</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0786em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8286em;"><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p>という解釈を入れる.さっき考えた例外のクライスリトリプルで,こいつらがどういう意味に当たるかを考えてみると,</p>
<ul class="simple">
<li>lift は,単純に例外の起きなかった計算結果を埋め込む.</li>
<li>let は,例外が起きるかもしれない計算を実行し,例外が起きたら次はスルー,起きなかったら計算結果を次に渡して次を実行する.</li>
</ul>
<p>という操作に当たる.で.クライスリトリプルの条件は,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mo>≡</mo><mo stretchy="false">(</mo><mo><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow></mo><msup><mi>x</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>←</mo><mo stretchy="false">[</mo><mi>x</mi><mo stretchy="false">]</mo><mo><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow></mo><mi>e</mi><mo stretchy="false">[</mo><mi>x</mi><mo>:</mo><mo>=</mo><msup><mi>x</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">]</mo><mo stretchy="false">)</mo><mo>≡</mo><mo stretchy="false">(</mo><mo><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow></mo><msup><mi>x</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>←</mo><mi>e</mi><mo><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow></mo><mo stretchy="false">[</mo><msup><mi>x</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
e
\equiv
(\mathop{\mathbf{let}} x' \gets [x] \mathop{\mathbf{in}} e[x := x'])
\equiv
(\mathop{\mathbf{let}} x' \gets e \mathop{\mathbf{in}} [x'])
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mop"><span class="mord"><span class="mord mathbf">let</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal">x</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mopen">[</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">])</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mop"><span class="mord"><span class="mord mathbf">let</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">in</span></span></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">])</span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mo><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow></mo><msub><mi>x</mi><mn>1</mn></msub><mo>←</mo><msub><mi>e</mi><mn>1</mn></msub><mo><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow></mo><mo><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow></mo><msub><mi>x</mi><mn>2</mn></msub><mo>←</mo><msub><mi>e</mi><mn>2</mn></msub><mo><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow></mo><msub><mi>e</mi><mn>3</mn></msub><mo stretchy="false">)</mo><mo>≡</mo><mo stretchy="false">(</mo><mo><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow></mo><msub><mi>x</mi><mn>2</mn></msub><mo>←</mo><mo><mrow><mi mathvariant="bold">l</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi></mrow></mo><msub><mi>x</mi><mn>1</mn></msub><mo>←</mo><msub><mi>e</mi><mn>1</mn></msub><mo><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow></mo><msub><mi>e</mi><mn>2</mn></msub><mo><mrow><mi mathvariant="bold">i</mi><mi mathvariant="bold">n</mi></mrow></mo><msub><mi>e</mi><mn>3</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
(\mathop{\mathbf{let}} x_1 \gets e_1 \mathop{\mathbf{in}} \mathop{\mathbf{let}} x_2 \gets e_2 \mathop{\mathbf{in}} e_3)
\equiv
(\mathop{\mathbf{let}} x_2 \gets \mathop{\mathbf{let}} x_1 \gets e_1 \mathop{\mathbf{in}} e_2 \mathop{\mathbf{in}} e_3)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mop"><span class="mord"><span class="mord mathbf">let</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">let</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mop"><span class="mord"><span class="mord mathbf">let</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">let</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mord"><span class="mord mathbf">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
<p>というコヒーレンスに対応している.クライスリトリプルの各要素が,それぞれの構文の解釈を担うのはかなり綺麗だ.で,上のコヒーレンスが成り立つので,元の言語の意味論で equational reasoning がいい感じの性質を持ったまま作れるなら,こちら用にも拡張できる.後は,言語の機能に合わせていい感じのクライスリトリプルを作ってやって,表層言語にいい感じの意味論を与えてやれば,それらを元に言語機能に合わせた意味論を構成してやることができるというわけだ.</p>
<p>この表層言語から切り離された,モナド (クライスリトリプル) の部分が,いわゆる計算作用 (computational effect) と呼ばれる部分だ.</p>
</div>
<div class="section" id="lax-monoidal-functor">
<h2>モナドは lax monoidal functor<a class="headerlink" href="#lax-monoidal-functor" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,モナドによりエフェクトと表層言語の分離がしやすくなるわけだけど,この分野ではもう一つ大きな需要があったらしく,それがエフェクト解析と呼ばれる分野らしい.今までは,エフェクトと表層言語両方用意する話をしてきたわけだけど,逆に表層言語だけ見てエフェクトの近似が出来ないか,特にどういう場所でどういうエフェクトが起こるかをもうちょっと詳細に見れないかという研究があったっぽい.で,このエフェクトの類推を型システムに載せられないかという話があり,それが今日のエフェクトシステムにつながる.</p>
<p>で,起こりうるエフェクトの種類が限られていて,それに名前がつけられる場合に,ある式に対して型とともに起こりうるエフェクトが追加された情報のジャッジメントができないだろうかというのが考えられた.そして,それを上のモナドを使った意味論の形で表現できないかというわけだ.イメージとしては,以下の感じ.</p>
<img alt="エフェクトに相当する,結合演算と比較演算上の情報が型に付加された,メタ言語." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-and-effects/graded-monad-and-effects/effectful-meta-syntax.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mi>ϵ</mi></mpadded></mover><msub><mi>τ</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">f: \tau_1 \xrightarrow{\epsilon} \tau_2</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0734em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9234em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> は関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi></mrow><annotation encoding="application/x-tex">f</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span></span> を実行するとエフェクト <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">\epsilon</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span></span></span></span></span> が発生すると読む. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn></mrow><annotation encoding="application/x-tex">1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> は単位的なエフェクトで,エフェクト同士には二項演算がある.また,エフェクト同士には順序があって,その順序に対してアップキャストルールがある.この言語に対して,モナドの意味論と同じように categorical な意味論のある表層言語から意味論を構築できないか考えたい.無理やりモナドによる意味論と同じ形で当てはめてみると,以下のようなものが出来上がる.</p>
<ul class="simple">
<li>effect: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mo>−</mo><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub></mrow><annotation encoding="application/x-tex">⟦-⟧_{\mathcal{E}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord">−</span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span></span></span></span></span> は,以下を満たす.<ul>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mn>1</mn><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">⟦1⟧_{\mathcal{E}} = 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord">1</span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⋅</mo><msub><mi>ϵ</mi><mn>2</mn></msub><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo>=</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>ϵ</mi><mn>1</mn></msub><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo>⋅</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>ϵ</mi><mn>2</mn></msub><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub></mrow><annotation encoding="application/x-tex">⟦\epsilon_1 \cdot \epsilon_2⟧_{\mathcal{E}} = ⟦\epsilon_1⟧_{\mathcal{E}} \cdot ⟦\epsilon_2⟧_{\mathcal{E}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
</li>
<li>type lift: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>ϵ</mi><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>τ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">T ⟦\epsilon⟧_{\mathcal{E}} ⟦\tau⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">ϵ</span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></li>
<li>lift: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>⊢</mo><mi>e</mi><mo>:</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><msub><mi>η</mi><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow></msub><mo>:</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>1</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>→</mo><mi>T</mi><mn>1</mn><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">⟦x: \tau_1 \vdash e: \tau_2⟧; \eta_{⟦\tau_2⟧}: ⟦\tau_1⟧ \to T 1 ⟦\tau_2⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight"><span class="mopen mtight">[</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mopen mtight">[</span></span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.1132em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight"><span class="mclose mtight">]</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mclose mtight">]</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></li>
<li>effectful app: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><mi>τ</mi><mo>⊢</mo><mi>e</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>1</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mover><mo minsize="3.0em" stretchy="true">→</mo><mpadded lspace="0.3em" width="+0.6em"><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>f</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow></mpadded></mover><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>ϵ</mi><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>:</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>τ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>→</mo><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>ϵ</mi><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">⟦x: \tau \vdash e: \tau_1⟧; ⟦\tau_1⟧ \xrightarrow{⟦f⟧} T ⟦\epsilon⟧_{\mathcal{E}} ⟦\tau_2⟧: ⟦\tau⟧ \to T ⟦\epsilon⟧_{\mathcal{E}} ⟦\tau_2⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.397em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel x-arrow"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.147em;"><span style="top:-3.322em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight x-arrow-pad"><span class="mord mtight"><span class="mopen mtight"><span class="mopen mtight">[</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mopen mtight">[</span></span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mclose mtight"><span class="mclose mtight">]</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mclose mtight">]</span></span></span></span></span><span class="svg-align" style="top:-2.689em;"><span class="pstrut" style="height:2.7em;"></span><span class="hide-tail" style="height:0.522em;min-width:1.469em;"><svg height="0.522em" preserveaspectratio="xMaxYMin slice" viewbox="0 0 400000 522" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M0 241v40h399891c-47.3 35.3-84 78-110 128
-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20
11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7
39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85
-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5
-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67
151.7 139 205zm0 0v40h399900v-40z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.011em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">ϵ</span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">ϵ</span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></li>
<li>let: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>⊢</mo><msub><mi>e</mi><mn>1</mn></msub><mo>:</mo><mi>T</mi><msub><mi>ϵ</mi><mn>1</mn></msub><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>2</mn></msub><mo>⊢</mo><msub><mi>e</mi><mn>2</mn></msub><mo>:</mo><mi>T</mi><msub><mi>ϵ</mi><mn>2</mn></msub><msub><mi>τ</mi><mn>3</mn></msub><msup><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>∗</mo></msup><mo>:</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>1</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>→</mo><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⋅</mo><msub><mi>ϵ</mi><mn>2</mn></msub><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>3</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>=</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>⊢</mo><msub><mi>e</mi><mn>1</mn></msub><mo>:</mo><mi>T</mi><msub><mi>ϵ</mi><mn>1</mn></msub><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>ϵ</mi><mn>1</mn></msub><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>2</mn></msub><mo>⊢</mo><msub><mi>e</mi><mn>2</mn></msub><mo>:</mo><mi>T</mi><msub><mi>ϵ</mi><mn>2</mn></msub><msub><mi>τ</mi><mn>3</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><msubsup><mi>μ</mi><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>3</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><mrow><msub><mi>ϵ</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>ϵ</mi><mn>2</mn></msub></mrow></msubsup></mrow><annotation encoding="application/x-tex">⟦x: \tau_1 \vdash e_1: T \epsilon_1 \tau_2⟧; ⟦x: \tau_2 \vdash e_2: T \epsilon_2 \tau_3⟧^*: ⟦\tau_1⟧ \to T ⟦\epsilon_1 \cdot \epsilon_2⟧_{\mathcal{E}} ⟦\tau_3⟧ = ⟦x: \tau_1 \vdash e_1: T \epsilon_1 \tau_2⟧; T ⟦\epsilon_1⟧_{\mathcal{E}} ⟦x: \tau_2 \vdash e_2: T \epsilon_2 \tau_3⟧; \mu^{\epsilon_1, \epsilon_2}_{⟦\tau_3⟧}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0786em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8286em;"><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2975em;vertical-align:-0.5152em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7823em;"><span style="top:-2.3598em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight"><span class="mopen mtight">[</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mopen mtight">[</span></span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.1132em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight"><span class="mclose mtight">]</span><span class="mspace mtight" style="margin-right:-0.2082em;"></span><span class="mclose mtight">]</span></span></span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.5152em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li>effect ord: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mo>⊢</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⊑</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>=</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>ϵ</mi><mn>1</mn></msub><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo>⊑</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>ϵ</mi><mn>2</mn></msub><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub></mrow><annotation encoding="application/x-tex">⟦\vdash \epsilon_1 \sqsubseteq \epsilon_2⟧ = ⟦\epsilon_1⟧_{\mathcal{E}} \sqsubseteq ⟦\epsilon_2⟧_{\mathcal{E}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li>cast: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mi>x</mi><mo>:</mo><msub><mi>τ</mi><mn>1</mn></msub><mo>⊢</mo><mi>e</mi><mo>:</mo><mi>T</mi><msub><mi>ϵ</mi><mn>1</mn></msub><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo separator="true">;</mo><mi>T</mi><mo stretchy="false">(</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mo>⊢</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⊑</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo stretchy="false">)</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>:</mo><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>1</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mo>→</mo><mi>T</mi><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>ϵ</mi><mn>2</mn></msub><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><msub><mi>τ</mi><mn>2</mn></msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo></mrow><annotation encoding="application/x-tex">⟦x: \tau_1 \vdash e: T \epsilon_1 \tau_2⟧; T (⟦\vdash \epsilon_1 \sqsubseteq \epsilon_2⟧) ⟦\tau_2⟧: ⟦\tau_1⟧ \to T ⟦\epsilon_2⟧_{\mathcal{E}} ⟦\tau_2⟧</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mrel">⊢</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mclose">)</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1132em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span></span></span></span></span></li>
</ul>
<p>問題は,以下の 4 つの要素がどういうものになるかということ.</p>
<ul class="simple">
<li>エフェクトの解釈 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo lspace="0em" mathvariant="normal" rspace="0em">⟦</mo><mo>−</mo><msub><mo lspace="0em" mathvariant="normal" rspace="0em">⟧</mo><mi mathvariant="script">E</mi></msub></mrow><annotation encoding="application/x-tex">⟦-⟧_{\mathcal{E}}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mopen"><span class="mopen">[</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mopen">[</span></span><span class="mord">−</span><span class="mclose"><span class="mclose"><span class="mclose">]</span><span class="mspace" style="margin-right:-0.1778em;"></span><span class="mclose">]</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathcal mtight" style="margin-right:0.08944em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li>エフェクトを考慮した関手っぽい何か <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mi>ϵ</mi><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">T \epsilon: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⊑</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>:</mo><mi>T</mi><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⇒</mo><mi>T</mi><msub><mi>ϵ</mi><mn>2</mn></msub><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">T (\epsilon_1 \sqsubseteq \epsilon_2): T \epsilon_1 \Rightarrow T \epsilon_2: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
<li>自然変換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>η</mi><mo>:</mo><mrow><mi mathvariant="normal">I</mi><mi mathvariant="normal">d</mi></mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mi>T</mi><mn>1</mn><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">\eta: \mathrm{Id} \implies T 1: C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7184em;vertical-align:-0.024em;"></span><span class="mord"><span class="mord mathrm">Id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
<li>自然変換 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>μ</mi><mrow><msub><mi>ϵ</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>ϵ</mi><mn>2</mn></msub></mrow></msup><mo>:</mo><mi>T</mi><msub><mi>ϵ</mi><mn>1</mn></msub><mo separator="true">;</mo><mi>T</mi><msub><mi>ϵ</mi><mn>2</mn></msub><mo>⇒</mo><mi>T</mi><mo stretchy="false">(</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⋅</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>:</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">\mu^{\epsilon_1, \epsilon_2}: T \epsilon_1; T \epsilon_2 \Rightarrow T (\epsilon_1 \cdot \epsilon_2): C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8588em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
</ul>
<p>これらの要素は,もちろん何でもいいってわけではなく, equational reasoning を構築するため,コヒーレンスを満たす必要がある.コヒーレンスの形は,モナドから推定するなら,以下のような形になりそうだ.</p>
<img alt="モナドのコヒーレンスにエフェクトがついたもの." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-and-effects/graded-monad-and-effects/graded-monad-coherence.png"/>
<p>で,ここまでくると二項演算の性質も決まってきて,</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⋅</mo><mo stretchy="false">(</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo>⋅</mo><msub><mi>ϵ</mi><mn>3</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⋅</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>⋅</mo><msub><mi>ϵ</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">\epsilon_1 \cdot (\epsilon_2 \cdot \epsilon_3) = (\epsilon_1 \cdot \epsilon_2) \cdot \epsilon_3</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>⋅</mo><mi>ϵ</mi><mo>=</mo><mi>ϵ</mi><mo>=</mo><mi>ϵ</mi><mo>⋅</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">1 \cdot \epsilon = \epsilon = \epsilon \cdot 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span></li>
</ul>
<p>となる.つまりは,モノイドというわけ.順序と合わせると,エフェクトの解釈領域をある構造で一般化できる.それは, monoidal category だ. monoidal category とは,以下の要素の組 <a class="footnote-reference" href="#lax-monoidal-category" id="auto-id-3">[2]</a>.</p>
<ul class="simple">
<li>圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
<li>テンソル積: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⊗</mo><mo>:</mo><mi>C</mi><mo>×</mo><mi>C</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">\otimes: C \times C \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">⊗</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
<li>単位対象: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">I \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span></li>
</ul>
<p>で,以下を満たすもの.</p>
<ul class="simple">
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>A</mi><mn>2</mn></msub><mo separator="true">,</mo><msub><mi>A</mi><mn>3</mn></msub><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">A_1, A_2, A_3 \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> に対して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msub><mi>A</mi><mn>1</mn></msub><mo>⊗</mo><msub><mi>A</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>⊗</mo><msub><mi>A</mi><mn>3</mn></msub><mo>=</mo><msub><mi>A</mi><mn>1</mn></msub><mo>⊗</mo><mo stretchy="false">(</mo><msub><mi>A</mi><mn>2</mn></msub><mo>⊗</mo><msub><mi>A</mi><mn>3</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(A_1 \otimes A_2) \otimes A_3 = A_1 \otimes (A_2 \otimes A_3)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>∈</mo><mi mathvariant="normal">∣</mi><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">A \in |C|</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord">∣</span></span></span></span></span> に対して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mo>⊗</mo><mi>I</mi><mo>=</mo><mi>A</mi><mo>=</mo><mi>I</mi><mo>⊗</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">A \otimes I = A = I \otimes A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span></li>
</ul>
<p>そうすると,エフェクトを考慮したモナド的な何かは, lax monoidal functor として定式化できる.monoidal category <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>E</mi><mo separator="true">,</mo><mo>⋅</mo><mo separator="true">,</mo><msub><mn>1</mn><mi>E</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(E, \cdot, 1_E)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">⋅</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord">1</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>C</mi><mo separator="true">,</mo><mo>⊗</mo><mo separator="true">,</mo><msub><mn>1</mn><mi>C</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">(C, \otimes, 1_C)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">⊗</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord">1</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> への lax monoidal functor とは,以下の要素の組.</p>
<ul class="simple">
<li>関手: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>:</mo><mi>E</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">T: E \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
<li>射: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>η</mi><mo>:</mo><msub><mn>1</mn><mi>C</mi></msub><mo>→</mo><mi>T</mi><msub><mn>1</mn><mi>E</mi></msub></mrow><annotation encoding="application/x-tex">\eta: 1_C \to T 1_E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7944em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">1</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord">1</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></li>
<li>自然変換: <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi><mo>:</mo><mi>T</mi><mo>−</mo><mo lspace="0.22em" rspace="0.22em">⊗</mo><mi>T</mi><mo>−</mo><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mi>T</mi><mo stretchy="false">(</mo><mo>−</mo><mo>⋅</mo><mo>−</mo><mo stretchy="false">)</mo><mo>:</mo><mi>E</mi><mo>×</mo><mi>E</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">\mu: T - \mathbin{\otimes} T - \implies T (- \cdot -): E \times E \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">μ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">⊗</span></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></li>
</ul>
<p>で,以下を満たすもの.</p>
<img alt="エフェクト側のモノイド則も考慮したコヒーレンス規則." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/06/graded-monad-and-effects/graded-monad-and-effects/lax-monoidal-functor-coherence.png"/>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> 上のモナドは, 1 から自己関手圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mi>C</mi><mo separator="true">,</mo><mi>C</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mo separator="true">;</mo><mo separator="true">,</mo><mrow><mi mathvariant="normal">I</mi><mi mathvariant="normal">d</mi></mrow><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">([C, C], ;, \mathrm{Id})</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">([</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">]</span><span class="mpunct">,;,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">Id</span></span><span class="mclose">)</span></span></span></span></span> <a class="footnote-reference" href="#tensor-of-endofunctors-is-opp" id="auto-id-4">[3]</a> への lax monoidal functor に一致する.いわゆる,自己関手圏でのモノイド対象というやつで,一般に monoidal category のモノイド対象とは 1 からの lax monoidal functor のこと.エフェクトを考慮した意味論を与える時に考えていたものは,モナドの一般化で,エフェクトの解釈領域である monoidal category <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi></mrow><annotation encoding="application/x-tex">E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> からいい感じの意味論が与えられている圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> を元にした自己関手圏 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mi>C</mi><mo separator="true">,</mo><mi>C</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[C, C]</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">]</span></span></span></span></span> への lax monoidal functor になる.で,この場合の lax monoidal functor のコヒーレンスを簡略したものが,モナドから無理やり導出したコヒーレンス則になる.</p>
</div>
<div class="section" id="auto-id-5">
<h2>graded monad とエフェクトシステム<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>この monoidal category から自己関手圏への lax monoidal functor のことを graded monad というらしい.またの名を parametric monad で, monad において 1 から自己関手圏の lax monoidal functor だったものを 1 の部分を任意の monoidal category にしてパラメータとしてとれるようにしたということだ.</p>
<p>実際には拡張した意味論を考える際には,エフェクトが monoidal category まで弱めるとちょっと不便なことがあって,今回エフェクトの射は順序づけに使うだけなので,対象間に複数射が伸びてるみたいな必要はない.なので, monoidal category をさらに制限して, preorder (反射推移的な二項関係) と monoid がある構造 preordered monoid を採用するっぽい.で,この preoredered monoid から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mi>C</mi><mo separator="true">,</mo><mi>C</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[C, C]</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">]</span></span></span></span></span> への lax monoidal functor を使って,モナドの時と同じように意味論の自然な拡張を行うという話になる.</p>
<p>で,表層言語から (preordered monoid に制限した) graded monad を使って拡張した言語をエフェクトシステムと呼ぶらしい.広義的には,前に紹介したエフェクトの細かい推定ができる型システムのことかしら?</p>
<p>例えば,以下のような graded monad <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>:</mo><mi>E</mi><mo>→</mo><mo stretchy="false">[</mo><mi>C</mi><mo separator="true">,</mo><mi>C</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">T: E \to [C,C]</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">]</span></span></span></span></span> を考えてみる.</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mi>ϵ</mi><mo>=</mo><msub><mo>∫</mo><mrow><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∈</mo><mi>E</mi></mrow></msub><mo stretchy="false">(</mo><mo>−</mo><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><mi>ϵ</mi><mo>⋅</mo><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><msup><mo stretchy="false">)</mo><mrow><mi>S</mi><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow></msup></mrow><annotation encoding="application/x-tex">
T \epsilon = \int_{\epsilon' \in E} (- \times S (\epsilon \cdot \epsilon'))^{S \epsilon'}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2993em;vertical-align:-0.9393em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right:0.44445em;position:relative;top:-0.0011em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-0.4336em;"><span style="top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.9393em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2425em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9925em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<p>ここで, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi><mo>:</mo><mi>E</mi><mo>→</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">S: E \to C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> は関手.こいつは state モナドの graded monad 版. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>η</mi><mo>:</mo><mrow><mi mathvariant="normal">I</mi><mi mathvariant="normal">d</mi></mrow><mo>⇒</mo><mi>T</mi><mn>1</mn></mrow><annotation encoding="application/x-tex">\eta: \mathrm{Id} \Rightarrow T 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">Id</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span></span></span></span></span> は,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mn>1</mn><mi>τ</mi><mo>=</mo><msub><mo>∫</mo><mrow><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∈</mo><mi>E</mi></mrow></msub><mo stretchy="false">(</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><mn>1</mn><mo>⋅</mo><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><msup><mo stretchy="false">)</mo><mrow><mi>S</mi><msup><mi>ϵ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow></msup><mo>=</mo><msub><mo>∫</mo><mrow><mi>ϵ</mi><mo>∈</mo><mi>E</mi></mrow></msub><mo stretchy="false">(</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mi>ϵ</mi><msup><mo stretchy="false">)</mo><mrow><mi>S</mi><mi>ϵ</mi></mrow></msup></mrow><annotation encoding="application/x-tex">
T 1 \tau
= \int_{\epsilon' \in E} (\tau \times S (1 \cdot \epsilon'))^{S \epsilon'}
= \int_{\epsilon \in E} (\tau \times S \epsilon)^{S \epsilon}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2993em;vertical-align:-0.9393em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right:0.44445em;position:relative;top:-0.0011em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-0.4336em;"><span style="top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.9393em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2425em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9925em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2993em;vertical-align:-0.9393em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right:0.44445em;position:relative;top:-0.0011em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-0.4336em;"><span style="top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.9393em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1413em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">ϵ</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mord mathnormal mtight">ϵ</span></span></span></span></span></span></span></span></span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>τ</mi><mo separator="true">,</mo><mo stretchy="false">(</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mi>ϵ</mi><msup><mo stretchy="false">)</mo><mrow><mi>S</mi><mi>ϵ</mi></mrow></msup><mo stretchy="false">)</mo><mo>≃</mo><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mi>C</mi></msub><mo stretchy="false">(</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mi>ϵ</mi><mo separator="true">,</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mi>ϵ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\mathrm{Hom}_C(\tau, (\tau \times S \epsilon)^{S \epsilon}) \simeq \mathrm{Hom}_C(\tau \times S \epsilon, \tau \times S \epsilon)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1413em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">ϵ</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mord mathnormal mtight">ϵ</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">ϵ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span></span></span></span></span></div>
<p>なことから,エンドの一意な射を持ってくることができる. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>μ</mi><mrow><msub><mi>ϵ</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>ϵ</mi><mn>2</mn></msub></mrow></msup><mo>:</mo><mi>T</mi><msub><mi>ϵ</mi><mn>1</mn></msub><mo separator="true">;</mo><mi>T</mi><msub><mi>ϵ</mi><mn>2</mn></msub><mo>⇒</mo><mi>T</mi><mo stretchy="false">(</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⋅</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mu^{\epsilon_1,\epsilon_2}: T \epsilon_1; T \epsilon_2 \Rightarrow T (\epsilon_1 \cdot \epsilon_2)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8588em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> は,エンドと冪の射を使って,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><msub><mi>ϵ</mi><mn>2</mn></msub><mo stretchy="false">(</mo><mi>T</mi><mi>ϵ</mi><mn>1</mn><mi>τ</mi><mo stretchy="false">)</mo><mo>×</mo><mi>S</mi><mi>ϵ</mi><mo>→</mo><mo stretchy="false">(</mo><mi>T</mi><mi>ϵ</mi><mn>1</mn><mi>τ</mi><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo>⋅</mo><mi>ϵ</mi><mo stretchy="false">)</mo><msup><mo stretchy="false">)</mo><mrow><mi>S</mi><mi>ϵ</mi></mrow></msup><mo>×</mo><mi>S</mi><mi>ϵ</mi><mo>→</mo><mi>T</mi><mi>ϵ</mi><mn>1</mn><mi>τ</mi><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo>⋅</mo><mi>ϵ</mi><mo stretchy="false">)</mo><mo>→</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><msub><mi>ϵ</mi><mn>1</mn></msub><mo>⋅</mo><msub><mi>ϵ</mi><mn>2</mn></msub><mo>⋅</mo><mi>ϵ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
T \epsilon_2 (T \epsilon 1 \tau) \times S \epsilon
\to (T \epsilon 1 \tau \times S (\epsilon_2 \cdot \epsilon))^{S \epsilon} \times S \epsilon
\to T \epsilon 1 \tau \times S (\epsilon_2 \cdot \epsilon)
\to \tau \times S (\epsilon_1 \cdot \epsilon_2 \cdot \epsilon)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mord">1</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mord">1</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1413em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mord mathnormal mtight">ϵ</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mord">1</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">ϵ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span></span></span></span></span></div>
<p>という射が構成できるので,やはりエンドの一意な射を持ってくることができる.</p>
<p>例えば, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi><mo>=</mo><mrow><mi mathvariant="normal">S</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow></mrow><annotation encoding="application/x-tex">C = \mathrm{Set}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathrm">Set</span></span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi><mo>=</mo><mi mathvariant="script">P</mi><mo stretchy="false">(</mo><mi mathvariant="double-struck">N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">E = \mathcal{P}(\mathbb{N})</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathcal" style="margin-right:0.08222em;">P</span><span class="mopen">(</span><span class="mord mathbb">N</span><span class="mclose">)</span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi><mo>=</mo><mo stretchy="false">(</mo><mo>−</mo><mo stretchy="false">)</mo><mo>⇀</mo><mi mathvariant="double-struck">N</mi></mrow><annotation encoding="application/x-tex">S = (-) \rightharpoonup \mathbb{N}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇀</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">N</span></span></span></span></span> (射に対しては,単に定義域を広げる) を考えてみると,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mi>I</mi><mi>τ</mi><mo>=</mo><msub><mo>∫</mo><mrow><msup><mi>I</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>⊆</mo><mi mathvariant="double-struck">N</mi></mrow></msub><mo stretchy="false">(</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><mi>I</mi><mo>∪</mo><msup><mi>I</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><msup><mo stretchy="false">)</mo><mrow><mi>S</mi><msup><mi>I</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow></msup><mo>=</mo><msub><mo>∫</mo><mrow><msup><mi>I</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>⊆</mo><mi mathvariant="double-struck">N</mi></mrow></msub><msub><mrow><mi mathvariant="normal">H</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">m</mi></mrow><mrow><mi mathvariant="normal">S</mi><mi mathvariant="normal">e</mi><mi mathvariant="normal">t</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><msup><mi>I</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><mi>I</mi><mo>∪</mo><msup><mi>I</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="normal">N</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">t</mi></mrow><mo stretchy="false">(</mo><mi>S</mi><mo separator="true">,</mo><mi>τ</mi><mo>×</mo><mi>S</mi><mo stretchy="false">(</mo><mi>I</mi><mo>∪</mo><mo stretchy="false">(</mo><mo>−</mo><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
T I \tau
= \int_{I' \subseteq \mathbb{N}} (\tau \times S (I \cup I'))^{S I'}
= \int_{I' \subseteq \mathbb{N}} \mathrm{Hom}_{\mathrm{Set}}(S I', \tau \times S (I \cup I'))
= \mathrm{Nat}(S, \tau \times S (I \cup (-)))
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3671em;vertical-align:-1.0071em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right:0.44445em;position:relative;top:-0.0011em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-0.4297em;"><span style="top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mrel mtight">⊆</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.0071em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2425em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9925em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3671em;vertical-align:-1.0071em;"></span><span class="mop"><span class="mop op-symbol large-op" style="margin-right:0.44445em;position:relative;top:-0.0011em;">∫</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-0.4297em;"><span style="top:-1.7881em;margin-left:-0.4445em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mrel mtight">⊆</span><span class="mord mathbb mtight">N</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.0071em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">Hom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathrm mtight">Set</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0519em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">Nat</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mclose">)))</span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>η</mi><mi>τ</mi></msub><mo>:</mo><mi>τ</mi><mo>→</mo><mi>T</mi><mi mathvariant="normal">∅</mi><mi>τ</mi><mo separator="true">;</mo><mi>x</mi><mo>↦</mo><mo stretchy="false">(</mo><mi>s</mi><mo>↦</mo><mo stretchy="false">(</mo><mi>x</mi><mo separator="true">,</mo><mi>s</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\eta_\tau: \tau \to T \emptyset \tau; x \mapsto (s \mapsto (x, s))
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.1132em;">τ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9444em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">∅</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mclose">))</span></span></span></span></span></div>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>μ</mi><mi>τ</mi><mrow><msub><mi>I</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>I</mi><mn>2</mn></msub></mrow></msubsup><mo>:</mo><mo stretchy="false">(</mo><mi>T</mi><msub><mi>I</mi><mn>1</mn></msub><mo separator="true">;</mo><mi>T</mi><msub><mi>I</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mi>τ</mi><mo>→</mo><mi>T</mi><mo stretchy="false">(</mo><msub><mi>I</mi><mn>1</mn></msub><mo>∪</mo><msub><mi>I</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mi>τ</mi><mo separator="true">;</mo><mi>f</mi><mo>↦</mo><mo stretchy="false">(</mo><msub><mi>s</mi><mn>1</mn></msub><mo>↦</mo><mi>g</mi><mo stretchy="false">(</mo><msub><mi>s</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mspace width="1em"></mspace><mo stretchy="false">(</mo><mo stretchy="false">(</mo><mi>g</mi><mo separator="true">,</mo><msub><mi>s</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><msub><mi>s</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\mu^{I_1, I_2}_\tau: (T I_1; T I_2) \tau \to T (I_1 \cup I_2) \tau; f \mapsto (s_1 \mapsto g(s_2) \quad((g, s_2) = f(s_1)))
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.1383em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.1132em;">τ</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord mathnormal" style="margin-right:0.1132em;">τ</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">((</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)))</span></span></span></span></span></div>
<p>となり,自然数でアクセスできるメモリを状態とする state モナドとほぼ同じになることが分かる.異なるのは状態の型が変わっていく可能性があることで,今まで使用したメモリ番地のみがエフェクトとして現れる.こんな感じで,モナドにしてしまうと常に同じエフェクトの見積もりになるところを,もう少し細かく見ることができるようになるのがエフェクトシステムの特徴っぽい?</p>
<p>ところで, graded monad はパラメータを固定してもモナドにならない場合があることには注意.上の例だと, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>I</mi></mrow><annotation encoding="application/x-tex">I</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span></span> を固定すればモナドが作れるんだけど,一般に monoid は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϵ</mi><mo>⋅</mo><mi>ϵ</mi><mo>=</mo><mi>ϵ</mi></mrow><annotation encoding="application/x-tex">\epsilon \cdot \epsilon = \epsilon</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">ϵ</span></span></span></span></span> とは限らないので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>μ</mi><mrow><mi>ϵ</mi><mo separator="true">,</mo><mi>ϵ</mi></mrow></msup><mo>:</mo><mi>T</mi><mi>ϵ</mi><mo separator="true">;</mo><mi>T</mi><mi>ϵ</mi><mo>⇒</mo><mi>T</mi><mo stretchy="false">(</mo><mi>ϵ</mi><mo>⋅</mo><mi>ϵ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mu^{\epsilon,\epsilon}: T \epsilon; T \epsilon \Rightarrow T (\epsilon \cdot \epsilon)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8588em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">μ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϵ</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">ϵ</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord mathnormal">ϵ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϵ</span><span class="mclose">)</span></span></span></span></span> がモナドの <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>μ</mi></mrow><annotation encoding="application/x-tex">\mu</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">μ</span></span></span></span></span> に一致しない.ただ, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>⋅</mo><mn>1</mn><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">1 \cdot 1 = 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span> なので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mn>1</mn></mrow><annotation encoding="application/x-tex">T 1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span></span></span></span></span> はモナドになる.</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>エフェクトシステム勉強会からだいぶ経ってしまったけど,とりあえず調べたことを簡単にまとめた.お気持ちが何となく分かったので,結構論文が読めて楽しい.</p>
<p>エフェクトシステムと聞くと algebraic effect とかプログラミング機能寄りの話にいきがちだったけど,そもそも新たな型システムとして,モナドによる意味論をもうちょっとやれる部分があるやろという感じの話なんだなというのが分かってきた (Plotkin 大先生によるエフェクトシステム勉強会の方,行けてない勢並の感想) .</p>
<p>indexed monad とかも実際には,エフェクトシステムの方やりたいやつもいくつかありそうやなみたいなことも思った. algebraic effect の意味論を考える場合,また違った話になるっぽいけど,</p>
<table class="docutils footnote" frame="void" id="category-has-coproduct" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>何の断りもなく直和が出てきてるが,もちろん直和が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> にあるとは限らない.ただ,ここではいい感じの意味論がある前提で話を進めているので,直和もあるという前提で話を進めている.以降も <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span> にいい感じの性質を断りなしに要求している場合があるが,ここではそういう前提を暗黙のうちに置いてるのねと思ってくれ.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="lax-monoidal-category" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[2]</a></td><td>通常の monoidal category は,他に 3 つの自然同型が付随していて,結合律を弱める <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>α</mi><mrow><mi>A</mi><mo separator="true">,</mo><mi>B</mi><mo separator="true">,</mo><mi>C</mi></mrow></msub><mo>:</mo><mo stretchy="false">(</mo><mi>A</mi><mo>⊗</mo><mi>B</mi><mo stretchy="false">)</mo><mo>⊗</mo><mi>C</mi><mo>≃</mo><mi>A</mi><mo>⊗</mo><mo stretchy="false">(</mo><mi>B</mi><mo>⊗</mo><mi>C</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\alpha_{A, B, C}: (A \otimes B) \otimes C \simeq A \otimes (B \otimes C)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">)</span></span></span></span></span> ,単位元律を弱める <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>λ</mi><mi>A</mi></msub><mo>:</mo><mi>I</mi><mo>⊗</mo><mi>A</mi><mo>≃</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">\lambda_A: I \otimes A \simeq A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">λ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>ρ</mi><mi>A</mi></msub><mo>:</mo><mi>A</mi><mo>⊗</mo><mi>I</mi><mo>≃</mo><mi>A</mi></mrow><annotation encoding="application/x-tex">\rho_A: A \otimes I \simeq A</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span></span></span></span></span> を設け,いい感じのコヒーレンス規則を設定する.今回の定義はこれらが恒等変換となっている場合で, strict monoidal category と呼ばれる.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="tensor-of-endofunctors-is-opp" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[3]</a></td><td>通常の自己関手圏は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∘</mo></mrow><annotation encoding="application/x-tex">\circ</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord">∘</span></span></span></span></span> をテンソル積に据えるけど,今回は書きやすさのため,その flip 版を用いている.言ってることは変わらないので,気にしないでくれ.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/06/graded-monad-and-effects.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/06/graded-monad-and-effects.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Apache Spark のお試し環境を作る2019-05-21T05:33:33+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-05-21:/blog/posts/2019/05/spark-installation-for-try/<p>Spark は <tt class="docutils literal"><span class="pre">spark-shell</span></tt> という対話式のお試し環境がついていて,かなりちょっと実行してみる系がやりやすそう.なので,そのための …</p><p>Spark は <tt class="docutils literal"><span class="pre">spark-shell</span></tt> という対話式のお試し環境がついていて,かなりちょっと実行してみる系がやりやすそう.なので,そのための環境を Docker で作った.その備忘録.</p>
<p>なお, <a class="reference external" href="https://github.com/Semantive/docker-spark">https://github.com/Semantive/docker-spark</a> を参考にさせてもらった.と言っても,最終的にかなり似通ったものになってしまったが.</p>
<div class="section" id="docker">
<h2>Docker の初期設定を書く<a class="headerlink" href="#docker" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>基本的な構成は,</p>
<ul class="simple">
<li><tt class="docutils literal">Dockerfile</tt> : Hadoop と Spark が入ったイメージの設定</li>
<li><tt class="docutils literal"><span class="pre">docker-compose.yml</span></tt> : master と worker の協調動作の設定</li>
<li><tt class="docutils literal">scripts/entrypoint.bash</tt> : イメージを起動した時の実行スクリプト</li>
</ul>
<p>にする.ベースイメージとしては, <tt class="docutils literal"><span class="pre">openjdk:8-jre</span></tt> を使う:</p>
<pre class="literal-block">
FROM openjdk:8-jre
</pre>
<p>元々は <tt class="docutils literal"><span class="pre">openjdk:9-jre</span></tt> で試してみてたんだけど, Spark の起動時に次のような警告が出るので,</p>
<pre class="literal-block">
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.spark.unsafe.Platform (file:/opt/spark/jars/spark-unsafe_2.11-2.4.3.jar) to method java.nio.Bits.unaligned()
WARNING: Please consider reporting this to the maintainers of org.apache.spark.unsafe.Platform
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
</pre>
<p>一応 8 にバージョンを落としとくことにした. <tt class="docutils literal">openjdk</tt> のイメージは, Debian をベースに作られてる.なので,まず Debian 用の初期設定コードを書いておく:</p>
<pre class="literal-block">
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
apt-utils locales wget \
&& update-locale LANG=C.UTF-8 LC_MESSAGES=POSIX \
&& locale-gen en_US.UTF-8 \
&& DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales \
&& rm -rf /var/lib/apt/lists/*
</pre>
</div>
<div class="section" id="hadoop-spark">
<h2>Hadoop と Spark のインストール<a class="headerlink" href="#hadoop-spark" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>次は, Hadoop と Spark のインストール設定.公式のプレビルドアーカイブを使う.両者,設定は大体一緒. Hadoop の方は次の感じになる:</p>
<pre class="literal-block">
ENV HADOOP_VERSION="2.7.7" \
HADOOP_CHECKSUM="17c8917211dd4c25f78bf60130a390f9e273b0149737094e45f4ae5c917b1174b97eb90818c5df068e607835120126281bcc07514f38bd7fd3cb8e9d3db1bdde" \
HADOOP_INSTALL_DIR="/opt/hadoop"
ENV HADOOP_HOME="${HADOOP_INSTALL_DIR}" \
HADOOP_CONF_DIR="${SPARK_INSTALL_DIR}/etc/hadoop"
RUN useradd --system --create-home --home-dir "${HADOOP_HOME}" hadoop \
&& mkdir -p "${HADOOP_INSTALL_DIR}" \
&& cd "${HADOOP_INSTALL_DIR}" \
&& wget -q -O "${HADOOP_INSTALL_DIR}/hadoop.tgz" "https://archive.apache.org/dist/hadoop/common/hadoop-${HADOOP_VERSION}/hadoop-${HADOOP_VERSION}.tar.gz" \
&& sha512sum "hadoop.tgz" | grep "${HADOOP_CHECKSUM}" \
&& tar -xz --strip 1 -f "hadoop.tgz" \
&& chown -R hadoop:hadoop "${HADOOP_HOME}"
</pre>
<p><tt class="docutils literal">hadoop</tt> システムユーザを作り,公式からアーカイブを落としてきて,チェックサムで検査して,展開し,所有権を <tt class="docutils literal">hadoop</tt> ユーザにする.落としてくる場所は, <tt class="docutils literal">/opt/hadoop</tt> ディレクトリ.なお, <tt class="docutils literal">HADOOP_HOME</tt> などがちゃんと設定されていないと, Spark が動かない. Spark の方は,次のように設定する:</p>
<pre class="literal-block">
ENV SPARK_VERSION="2.4.3" \
SPARK_CHECKSUM="e8b7f9e1dec868282cadcad81599038a22f48fb597d44af1b13fcc76b7dacd2a1caf431f95e394e1227066087e3ce6c2137c4abaf60c60076b78f959074ff2ad" \
SPARK_INSTALL_DIR="/opt/spark"
ENV SPARK_HOME="${SPARK_INSTALL_DIR}" \
SPARK_CONF_DIR="${SPARK_INSTALL_DIR}/conf"
RUN useradd --system --create-home --home-dir "${SPARK_HOME}" spark \
&& mkdir -p "${SPARK_INSTALL_DIR}" \
&& cd "${SPARK_INSTALL_DIR}" \
&& wget -q -O "${SPARK_INSTALL_DIR}/spark-bin-hadoop.tgz" "https://archive.apache.org/dist/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION%.*}.tgz" \
&& sha512sum "spark-bin-hadoop.tgz" | grep "${SPARK_CHECKSUM}" \
&& tar -xz --strip 1 -f "spark-bin-hadoop.tgz" \
&& chown -R spark:spark "${SPARK_HOME}"
</pre>
<p>見ての通り, Hadoop とほぼ同じだ.後は, エントリーポイントを書いて設定するだけ.ただ,それだけだとちょっと不便なので次の設定も書いておく:</p>
<pre class="literal-block">
ENV PATH="${SPARK_INSTALL_DIR}/bin:${PATH}" \
LD_LIBRARY_PATH="${HADOOP_HOME}/lib/native:${LD_LIBRARY_PATH}"
</pre>
<p><tt class="docutils literal">PATH</tt> の設定は, <tt class="docutils literal"><span class="pre">spark-shell</span></tt> などを実行パスに含める為.二つ目の設定は,書かないと次の警告が発生する:</p>
<pre class="literal-block">
WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
</pre>
</div>
<div class="section" id="auto-id-1">
<h2>エントリーポイントの設定<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>エントリーポイントとして,次のバッシュスクリプト <tt class="docutils literal">scripts/entrypoint.bash</tt> を作成した:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span></pre></div></td><td class="code"><div><pre><span></span><span class="ch">#!/usr/bin/env bash</span>
<span class="o">[[</span><span class="w"> </span><span class="s2">"</span><span class="nv">$DEBUG</span><span class="s2">"</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s2">"true"</span><span class="w"> </span><span class="o">]]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nb">set</span><span class="w"> </span>-x
<span class="o">[[</span><span class="w"> </span><span class="s2">"</span><span class="nv">$STRICT</span><span class="s2">"</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s2">"true"</span><span class="w"> </span><span class="o">]]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="nb">set</span><span class="w"> </span>-u
<span class="nb">set</span><span class="w"> </span>-eo<span class="w"> </span>pipefail
<span class="k">case</span><span class="w"> </span><span class="si">${</span><span class="nv">1</span><span class="si">}</span><span class="w"> </span><span class="k">in</span>
<span class="w"> </span>master<span class="o">)</span>
<span class="w"> </span><span class="nb">shift</span><span class="w"> </span><span class="m">1</span>
<span class="w"> </span><span class="nb">exec</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">SPARK_INSTALL_DIR</span><span class="si">}</span><span class="s2">/bin/spark-class"</span><span class="w"> </span><span class="s2">"org.apache.spark.deploy.master.Master"</span><span class="w"> </span><span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span>
<span class="w"> </span><span class="p">;;</span>
<span class="w"> </span>worker<span class="o">)</span>
<span class="w"> </span><span class="nb">shift</span><span class="w"> </span><span class="m">1</span>
<span class="w"> </span><span class="nb">exec</span><span class="w"> </span><span class="s2">"</span><span class="si">${</span><span class="nv">SPARK_INSTALL_DIR</span><span class="si">}</span><span class="s2">/bin/spark-class"</span><span class="w"> </span><span class="s2">"org.apache.spark.deploy.worker.Worker"</span><span class="w"> </span><span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span>
<span class="w"> </span><span class="p">;;</span>
<span class="w"> </span>*<span class="o">)</span>
<span class="w"> </span><span class="nb">exec</span><span class="w"> </span><span class="s2">"</span><span class="nv">$@</span><span class="s2">"</span>
<span class="w"> </span><span class="p">;;</span>
<span class="k">esac</span>
</pre></div></td></tr></table></div>
<p>こいつは, <tt class="docutils literal">master</tt> / <tt class="docutils literal">worker</tt> を1引数目に受け取ると, Spark のそれぞれのメインクラスを,それ以外の場合コマンドだと思ってそれを実行する.こいつを,コピーして,エントリーポイントとして設定する:</p>
<pre class="literal-block">
COPY scripts/entrypoint.bash /sbin/entrypoint.bash
RUN chmod 755 /sbin/entrypoint.bash
USER spark
WORKDIR $SPARK_HOME
ENTRYPOINT [ "/sbin/entrypoint.bash" ]
CMD ["master"]
</pre>
</div>
<div class="section" id="docker-compose">
<h2>Docker Compose の設定<a class="headerlink" href="#docker-compose" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>後は <tt class="docutils literal">master</tt> / <tt class="docutils literal">worker</tt> それぞれを一つずつインスタンスとして起動して,協調動作させるための設定を, Docker Compose で書く. <tt class="docutils literal">master</tt> は以下のようにする:</p>
<pre class="literal-block">
master:
build: .
command: ["master"]
hostname: master
environment:
MASTER: spark://master:7077
ports:
- 4040:4040
- 6066:6066
- 7077:7077
- 8080:8080
</pre>
<p>それぞれのポートは,</p>
<ul class="simple">
<li>4040: アプリケーション確認用 Web UI</li>
<li>8080: ジョブヒストリー確認用 Web UI</li>
<li>6066: Rest API</li>
<li>7077: ジョブサブミット用</li>
</ul>
<p>という感じっぽい.なお,設定できる環境変数は,コンテナを起動した後,以下で確認できる:</p>
<pre class="literal-block">
docker-compose exec master cat conf/spark-env.sh.template
</pre>
<p>なお, <tt class="docutils literal">MASTER</tt> は <tt class="docutils literal"><span class="pre">spark-shell</span></tt> などの CLI 用に設定している. CLI はこの変数を見て <tt class="docutils literal">master</tt> のジョブサブミット先を決めるっぽい. <tt class="docutils literal">worker</tt> の方は以下のように書く:</p>
<pre class="literal-block">
worker1:
build: .
command: ["worker", "spark://master:7077"]
depends_on:
- master
environment:
SPARK_WORKER_WEBUI_PORT: 8081
ports:
- 8081:8081
</pre>
<p>最終的にできたやつは, <a class="reference external" href="https://github.com/mizunashi-mana/docker-toy-spark">https://github.com/mizunashi-mana/docker-toy-spark</a> に上げてある.</p>
</div>
<div class="section" id="spark-shell">
<h2>spark-shell を動かす<a class="headerlink" href="#spark-shell" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>後は <tt class="docutils literal"><span class="pre">spark-shell</span></tt> を <tt class="docutils literal"><span class="pre">spark://localhost:7077</span></tt> に設定して起動すればいい:</p>
<pre class="literal-block">
spark-shell --master spark://localhost:7077
</pre>
<p><tt class="docutils literal">master</tt> のコンテナでも起動できて,次のようにする:</p>
<pre class="literal-block">
docker-compose exec master spark-shell
</pre>
<p><tt class="docutils literal"><span class="pre">spark-shell</span></tt> は <tt class="docutils literal">SparkContext</tt> が <tt class="docutils literal">sc</tt> に束縛されて,諸々がデフォルトで <tt class="docutils literal">import</tt> されてる sbt みたいな感じっぽい.例えば次のような入力ができる:</p>
<pre class="literal-block">
scala> sc.parallelize(0 until 100).flatMap { p => (0 until 100).map { i => ((p + i) % 40, i) } }.groupByKey().count()
res1: Long = 40
</pre>
<p>論理プランは次のメソッドで見れる:</p>
<pre class="literal-block">
scala> sc.parallelize(0 until 100).flatMap { p => (0 until 100).map { i => ((p + i) % 40, i) } }.groupByKey().toDebugString
res3: String =
(2) ShuffledRDD[11] at groupByKey at <console>:25 []
+-(2) MapPartitionsRDD[10] at flatMap at <console>:25 []
| ParallelCollectionRDD[9] at parallelize at <console>:25 []
</pre>
<p>最初の <tt class="docutils literal">(N)</tt> の <tt class="docutils literal">N</tt> はパーティション数, <tt class="docutils literal">[N]</tt> の <tt class="docutils literal">N</tt> は RDD の ID っぽい.例えば, <tt class="docutils literal">parallelize</tt> と <tt class="docutils literal">groupByKey</tt> でパーティション数を指定してみる:</p>
<pre class="literal-block">
scala> sc.parallelize(0 until 100, 100).flatMap { p => (0 until 100).map { i => ((p + i) % 40, i) } }.groupByKey(50).toDebugString
res5: String =
(50) ShuffledRDD[17] at groupByKey at <console>:25 []
+-(100) MapPartitionsRDD[16] at flatMap at <console>:25 []
| ParallelCollectionRDD[15] at parallelize at <console>:25 []
</pre>
<p>なお, <tt class="docutils literal">:q</tt> で閉じれる.アクションを実行すると,ジョブが発行される.ジョブは <tt class="docutils literal"><span class="pre">http://localhost:4040</span></tt> から見れる.画面は以下の感じ:</p>
<img alt="物理プランのステージ分けやタイムラインなどが見れる." src="https://mizunashi-mana.github.io/blog/posts/2019/05/spark-installation-for-try/spark-installation-for-try/application-ui-image.png"/>
<p>タスクの詳細は,ステージ欄にあるリンクから見れるっぽい.</p>
</div>
<div class="section" id="auto-id-2">
<h2>まとめ<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Spark ,プログラムが手軽に書けるし,対話的に色々試せて良さそう.</p>
<p>時折気を見て,色々試していきたいなあ.てことで,以上です.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/05/spark-installation-for-try.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/05/spark-installation-for-try.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>GHC で LLVM を通したビルドを行う2019-05-17T05:47:18+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-05-17:/blog/posts/2019/05/ghc-with-llvm/<p>GHC で LLVM を通してビルドをしたかったので,設定した.その備忘録.</p>
<div class="section" id="macos-llvm-ghc">
<h2>macOS で LLVM を GHC が使えるようにする<a class="headerlink" href="#macos-llvm-ghc" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>GHC が対応してる LLVM の …</p></div><p>GHC で LLVM を通してビルドをしたかったので,設定した.その備忘録.</p>
<div class="section" id="macos-llvm-ghc">
<h2>macOS で LLVM を GHC が使えるようにする<a class="headerlink" href="#macos-llvm-ghc" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>GHC が対応してる LLVM のバージョンは,標準で入ってるのよりちょっと古くって,さらにバージョンごとにサポートされてる範囲が違う.各 GHC でサポートされてる LLVM のバージョンは,以下に載ってる:</p>
<blockquote>
<a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/backends/llvm/installing#llvm-support">https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/backends/llvm/installing#llvm-support</a></blockquote>
<p>今回は GHC 8.6.5 を使ったので, LLVM のバージョンは 6 系になる.なので, LLVM 6 系を Homebrew でインストールする:</p>
<pre class="literal-block">
brew install llvm@6
</pre>
<p>後は, GHC が見にいく llvm のツールの場所をインストールしたものに変更する. GHC は <tt class="docutils literal">settings</tt> ファイルというものを持っている.これは単なるテキストファイルで, Haskell の <tt class="docutils literal">[(String, String)]</tt> 型のダンプ情報の形式で書かれていて,ユーザが書き換え可能だ. GHC は実行するたびにこのファイルを見て, <tt class="docutils literal">read :: String <span class="pre">-></span> [(String, String)]</tt> した情報を元に設定を初期化する.このファイルは, <tt class="docutils literal">lib</tt> ディレクトリのトップに置かれているのが通常で, <tt class="docutils literal">ghcup</tt> を使っている場合, <tt class="docutils literal"><span class="pre">~/.ghcup/ghc/8.6.5/lib/ghc-8.6.5/settings</span></tt> にある.この設定の LLVM 関連部分を修正する.主に修正する箇所は 2 つ:</p>
<pre class="literal-block">
[
...
("LLVM llc command", "llc"),
("LLVM opt command", "opt"),
("LLVM clang command", "clang")
]
</pre>
<p>のうちの <tt class="docutils literal">LLVM llc command</tt> と <tt class="docutils literal">LLVM opt command</tt> を LLVM 6 のパスに置き換える.置き換える場所は</p>
<pre class="literal-block">
$ echo $(brew --prefix llvm@6)/bin/{llc,opt}
/usr/local/opt/llvm@6/bin/llc /usr/local/opt/llvm@6/bin/opt
</pre>
<p>で,次のように書けばいい:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="w"> </span> [
<span class="w"> </span> ...
<span class="gd">- ("LLVM llc command", "llc"),</span>
<span class="gd">- ("LLVM opt command", "opt"),</span>
<span class="gi">+ ("LLVM llc command", "/usr/local/opt/llvm@6/bin/llc"),</span>
<span class="gi">+ ("LLVM opt command", "/usr/local/opt/llvm@6/bin/opt"),</span>
<span class="w"> </span> ("LLVM clang command", "clang")
<span class="w"> </span> ]
</pre></div></td></tr></table></div>
<div class="section" id="llvm-clang-command">
<h3>LLVM clang command について<a class="headerlink" href="#llvm-clang-command" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p><tt class="docutils literal">LLVM clang command</tt> はなんか変えなくても動くし,こいつを <tt class="docutils literal">/usr/local/opt/llvm@6/bin/clang</tt> に変えてコンパイルすると以下のエラーが出てコンパイルができない:</p>
<pre class="literal-block">
$ cabal new-build
...
/var/folders/km/7h33fnqs7bddrz_xtx609ss00000gn/T/ghc78032_0/ghc_1.s:2:31: error:
error: invalid OS update specifier, comma expected
.build_version macos, 10, 14 sdk_version 10, 14
^
|
2 | .build_version macos, 10, 14 sdk_version 10, 14
| ^
<no location info>: error:
Error running clang! you need clang installed to use the LLVM backend
(or GHC tried to execute clang incorrectly)
`clang' failed in phase `Clang (Assembler)'. (Exit code: 1)
</pre>
<p>原因不明だが, <tt class="docutils literal">LLVM clang command</tt> をいじらなければ普通に動くので,なんだろなって思って放置してる.原因誰か知ってたら教えてくださいって感じ.</p>
</div>
</div>
<div class="section" id="llvm">
<h2>LLVM を通してビルドする<a class="headerlink" href="#llvm" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>後は, <tt class="docutils literal"><span class="pre">-fllvm</span></tt> オプションをつけてビルドすればいい. <tt class="docutils literal">cabal</tt> の場合,</p>
<pre class="literal-block">
cabal build --ghc-options=-fflvm
</pre>
<p>みたいにする.ついでに,ネイティブビルドの場合 <tt class="docutils literal"><span class="pre">-fasm</span></tt> を付ける.なお, LLVM の出力が見たかったら <tt class="docutils literal"><span class="pre">-ddump-llvm</span></tt> というオプションで見れるっぽい. LLVM 出力ができてるかどうかは, <tt class="docutils literal"><span class="pre">-ddump-llvm</span></tt> と <tt class="docutils literal"><span class="pre">-ddump-asm</span></tt> をつけて <tt class="docutils literal">asm</tt> の出力が出てたら出来てない, <tt class="docutils literal">llvm</tt> の出力が出てたら出来てるって感じで確認できる.</p>
</div>
<div class="section" id="auto-id-1">
<h2>まとめ<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>macOS の環境の下, GHC で LLVM を使う方法を紹介した. LLVM 用のコード生成見る時とかに使っていきたい.後,パフォーマンスが劇的に改善するらしいね.</p>
<p>ただ, <tt class="docutils literal">ghcup</tt> を使っている場合一々 <tt class="docutils literal">settings</tt> を変更しなきゃいけないのは微妙なので,この辺なんとかしたいね.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/05/ghc-with-llvm.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/05/ghc-with-llvm.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>GHC IO モナドの中身2019-05-17T05:47:08+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-05-17:/blog/posts/2019/05/ghc-io-inside/<p>Haskell の IO モナドって,中身どうなってたんだろと気になってて,ちょっと調べてみた.そのメモ.</p>
<div class="section" id="io-realworld">
<h2>IO モナドと RealWorld<a class="headerlink" href="#io-realworld" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まずは基本 …</p></div><p>Haskell の IO モナドって,中身どうなってたんだろと気になってて,ちょっと調べてみた.そのメモ.</p>
<div class="section" id="io-realworld">
<h2>IO モナドと RealWorld<a class="headerlink" href="#io-realworld" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まずは基本から. IO モナドは, Haskell の根幹となるモナドで, <tt class="docutils literal">main</tt> も IO で書く. GHC では中身は次のように定義されている <a class="footnote-reference" href="#io-monad-definition" id="auto-id-1">[1]</a>:</p>
<pre class="literal-block">
-- In GHC.Types module of ghc-prim package
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
</pre>
<p>見ての通り, <tt class="docutils literal">IO a</tt> は <tt class="docutils literal">State# RealWorld <span class="pre">-></span> (# State# RealWorld, a #)</tt> の <tt class="docutils literal">newtype</tt> だ.あんまり見慣れない <tt class="docutils literal">State# RealWorld</tt> という型と <tt class="docutils literal">(# , #)</tt> という型が出てきたけど, <tt class="docutils literal">State# RealWorld</tt> の方は置いといて, <tt class="docutils literal">(# , #)</tt> からまず説明しておく.</p>
<p><tt class="docutils literal">(# , #)</tt> は特別に <tt class="docutils literal">IO</tt> のみ許可されてる型というわけではなく, GHC の <tt class="docutils literal">UnboxedTuples</tt> という拡張で提供される型.名前の通り, unboxed なタプルを提供してくれる.いわゆる多値というやつで,ヒープアロケーションされず,要素はレジスタかスタックに格納される.つまり, <tt class="docutils literal">s <span class="pre">-></span> (# s, a #)</tt> なのは特に性能とか実行時表現の違いを無視すれば, <tt class="docutils literal">s <span class="pre">-></span> (s, a)</tt> と書くのと同じ意味を持つ.なので, IO モナドとは型の定義だけ見れば, <tt class="docutils literal">State (State# RealWorld)</tt> モナドと同じことを表現してることになる.</p>
<p>次に <tt class="docutils literal">State# RealWorld</tt> とはなんなのかだけど, <tt class="docutils literal">State#</tt> , <tt class="docutils literal">RealWorld</tt> 両方プリミティブで,言語表層的には <tt class="docutils literal"><span class="pre">ghc-prim</span></tt> パッケージの <tt class="docutils literal">GHC.Prim</tt> モジュールで定義された,中身のいじれない型ということになる <a class="footnote-reference" href="#how-to-defined-primtypes" id="auto-id-2">[2]</a> .</p>
<p>GHC の IO モナドは,意味としては現実世界のコンテキストを表す <tt class="docutils literal">State# RealWorld</tt> を状態とする State モナドだ.ただ,単なる State モナドではなく,線形使用制約というものがついている.つまり,現在の状態として受け取った <tt class="docutils literal">State# RealWorld</tt> は,状態遷移において必ず 1 度だけ使わなければいけない.ただこの制約は, Haskell の型システムでは守られていることの保証ができない <a class="footnote-reference" href="#uniqueness-typing" id="auto-id-3">[3]</a> .そこで, GHC では IO に対する操作は隠蔽されている.そして, RTS が提供する IO 操作用のプリミティブ関数だけが <tt class="docutils literal">State# RealWorld</tt> を弄るようになっている.例えば,以下の <tt class="docutils literal">IORef</tt> を使用する IO モナドでのプログラム:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE BlockArguments #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Control.Concurrent</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">Data.IORef</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">newIORef</span><span class="w"> </span><span class="kt">True</span>
<span class="w"> </span><span class="n">writeIORef</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="n">readIORef</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>は,プリミティブ命令と明示的な <tt class="docutils literal">State# RealWorld</tt> の伝搬で書いてみると,以下のようになる <a class="footnote-reference" href="#ioref-use-mutvar-inside" id="auto-id-4">[4]</a> :</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE BangPatterns #-}</span>
<span class="cm">{-# LANGUAGE MagicHash #-}</span>
<span class="cm">{-# LANGUAGE UnboxedTuples #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">GHC.Base</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="n">go</span>
<span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">State</span><span class="o">#</span><span class="w"> </span><span class="kt">RealWorld</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kt">State</span><span class="o">#</span><span class="w"> </span><span class="kt">RealWorld</span><span class="p">,</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
<span class="w"> </span><span class="n">go</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span>
<span class="w"> </span><span class="kr">let</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s1</span><span class="o">#</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="o">#</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">newMutVar</span><span class="o">#</span><span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s2</span><span class="o">#</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">writeMutVar</span><span class="o">#</span><span class="w"> </span><span class="n">x</span><span class="o">#</span><span class="w"> </span><span class="kt">False</span><span class="w"> </span><span class="n">s1</span><span class="o">#</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s3</span><span class="o">#</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">readMutVar</span><span class="o">#</span><span class="w"> </span><span class="n">x</span><span class="o">#</span><span class="w"> </span><span class="n">s2</span><span class="o">#</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s3</span><span class="o">#</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>State モナドで,返り値が unboxed tuple になり,状態が <tt class="docutils literal">State# RealWorld</tt> に変わってるだけである.ランタイムは最終的にこの IO を受け取って,最初の <tt class="docutils literal">State# RealWorld</tt> を渡して実行していく.まさに現実世界を状態として実行されていく純粋関数が, Haskell のプログラムというわけである.ただ,現実世界というのはままならないもので,パッと状態を元に戻すといったことはできないし,状態を複製するというわけにも,元のまま保存するというわけにもいかない.このような制約と整合性がつくようにするのが,線形使用制約である.実際にこの制約が破られるとどうなるか,少し見てみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE BlockArguments #-}</span>
<span class="cm">{-# LANGUAGE BangPatterns #-}</span>
<span class="cm">{-# LANGUAGE MagicHash #-}</span>
<span class="cm">{-# LANGUAGE UnboxedTuples #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">GHC.Base</span>
<span class="c1">-- | Example of unsafe IO using</span>
<span class="c1">--</span>
<span class="c1">-- Some case:</span>
<span class="c1">--</span>
<span class="c1">-- >>> main</span>
<span class="c1">-- World</span>
<span class="c1">-- Hello</span>
<span class="c1">--</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nf">\</span><span class="n">s0</span><span class="o">#</span><span class="w"> </span><span class="ow">-></span>
<span class="w"> </span><span class="kr">let</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unIO</span><span class="w"> </span><span class="p">(</span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"Hello"</span><span class="p">)</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unIO</span><span class="w"> </span><span class="p">(</span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"World"</span><span class="p">)</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">unIO</tt> は単に <tt class="docutils literal">\(IO x) <span class="pre">-></span> x</tt> で, <tt class="docutils literal">GHC.Base</tt> で定義されている関数.上の関数は <tt class="docutils literal">s0#</tt> を3回 (出力部分で2回,返り値で1回の計3回) 使用しており,また捨ててる状態もあるなど,やりたい放題なわけだけど,元の状態 <tt class="docutils literal">s0#</tt> を返しているからといって何も出力されないわけでもないし,今回は想定と逆順とはいえ出力が行われているわけだが,最適化によっては片方しか出力がされないみたいなこともある.もちろん,エラーが起こった時に <tt class="docutils literal">main</tt> を <tt class="docutils literal">catch</tt> しても例外が取れるとも限らない.</p>
<p>現実世界は State モナドのように状態を気軽に <tt class="docutils literal">get</tt> / <tt class="docutils literal">put</tt> で差し戻したりすることはできない.実行した副作用を元に戻すことができないからだ. <tt class="docutils literal">putStrLn "Hello"</tt> を一度計算として走らせてしまえば,それを後から差し戻そうとしてももう出力してしまった後かもしれない.そうなれば,戻す作業は大掛かりだしそもそもユーザが見てしまった出力をなかったことになんてできない.それができてしまったら,タイムマシンの発明だ.ノーベル賞が取れるだろう. <tt class="docutils literal">IO</tt> はそのような事情を鑑みて,せめて実行タイミングを制御することを目的としたものだ.どの IO 処理の後に次の IO 処理を行うかを, <tt class="docutils literal">State# RealWorld</tt> を線形使用制約に従って伝搬させることで保証させる.さらに IO 操作そのものは, <tt class="docutils literal">State# RealWorld</tt> を渡してやらないと起動しない.これにより, IO 命令は第1級のデータとして扱えるわけだ. GHC のランタイムは, Haskell で扱えない <tt class="docutils literal">State# RealWorld</tt> の実体を定義し,初期の現実世界を表す状態を作って,それをユーザが定義した <tt class="docutils literal">main</tt> に渡してやるだけという感じになる.</p>
</div>
<div class="section" id="io">
<h2>IO コードの生成<a class="headerlink" href="#io" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ここからが本題.表面的には, IO モナドは以上の思想で運用されてるわけだけど,実際にこの線形な State モナドは GHC の内部でどのように扱われ,どのようなコード生成がされるんだろう? それをいろいろ調査してみた.なお,使ったのは GHC 8.6.5 .</p>
<p>まず, <tt class="docutils literal">State# RealWorld</tt> の実際の値は,サイズ 0 ,つまり何の情報も持たず,レジスタもスタックも特に消費しない値として使われる.なので,意味的には上記で述べた通り現実世界を表現する仮想の状態として扱われるが,実行時に愚直にそのような状態更新が行われるわけでないということだ.実際に,まずは IO を使ったプログラムが,コンパイル過程でどのように変遷していくかを見てみる.対象は以下のプログラム:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">import</span><span class="w"> </span><span class="nn">Data.IORef</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">do</span>
<span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow"><-</span><span class="w"> </span><span class="n">newIORef</span><span class="w"> </span><span class="kt">True</span>
<span class="w"> </span><span class="n">writeIORef</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="kt">False</span>
<span class="w"> </span><span class="n">readIORef</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p>このプログラムの <tt class="docutils literal"><span class="pre">-ddump-simpl</span></tt> は,以下のようになる:</p>
<pre class="literal-block">
main1
:: GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld, Bool #)
main1
= \ (s_i7hd :: GHC.Prim.State# GHC.Prim.RealWorld) ->
case GHC.Prim.newMutVar#
@ Bool @ GHC.Prim.RealWorld GHC.Types.True s_i7hd
of
{ (# ipv_i7ho, ipv1_i7hp #) ->
case GHC.Prim.writeMutVar#
@ GHC.Prim.RealWorld @ Bool ipv1_i7hp GHC.Types.False ipv_i7ho
of s2#_i7hT
{ __DEFAULT ->
GHC.Prim.readMutVar# @ GHC.Prim.RealWorld @ Bool ipv1_i7hp s2#_i7hT
}
}
main :: IO Bool
main
= main1
`cast` (Sym (GHC.Types.N:IO[0] <Bool>_R)
:: (GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld, Bool #))
~R# IO Bool)
</pre>
<p>余計な情報はかなり省いている. <tt class="docutils literal">main1</tt> の部分が本体で, <tt class="docutils literal">newtype</tt> が <tt class="docutils literal">cast</tt> に変換され,インライン展開と最適化によって余計なコンストラクタが消えた結果,上の方で述べた <tt class="docutils literal">State# RealWorld</tt> の明示的な伝搬におおよそ変換されている.後は, Core 特有の多相関数に対して型推論で推論された型の明示的な適用などが書かれている.ここらへんは, <tt class="docutils literal">TypeApplications</tt> 拡張で書かれたコードだと思えば素直に読めると思う.最終的な Core はほぼこの形で出力される.次にこの Core は <tt class="docutils literal"><span class="pre">-ddump-stg</span></tt> で見ると,以下のように変換される:</p>
<pre class="literal-block">
main1 =
[] \r [void_0E]
case newMutVar# [GHC.Types.True GHC.Prim.void#] of {
Unit# ipv1_s7lS ->
case
writeMutVar# [ipv1_s7lS GHC.Types.False GHC.Prim.void#]
of
s2#_s7lT
{ (##) -> readMutVar# [ipv1_s7lS GHC.Prim.void#];
};
};
main =
[] \r [void_0E] main1 GHC.Prim.void#;
</pre>
<p>STG の大雑把な読み方だけど, <tt class="docutils literal">[] \r <span class="pre">[...]</span> ...</tt> は関数を表すクロージャで最後の <tt class="docutils literal"><span class="pre">[...]</span></tt> に引数が並んでいて, <tt class="docutils literal">f <span class="pre">[...]</span></tt> は関数適用になる.なお, 1 引数の関数適用は <tt class="docutils literal">[]</tt> が省略される.Core と対応させれば雰囲気はなんとなく分かるだろう.注目して欲しいのは, <tt class="docutils literal">State# RealWorld</tt> の引数だった部分が,全て <tt class="docutils literal">void_XX</tt> という変数名に置き換わっていること,適用部分も <tt class="docutils literal">GHC.Prim.void#</tt> という値の適用に置き換わっていること,パターンマッチで unboxed tuple のマッチをしていた部分がそれぞれ <tt class="docutils literal">Unit#</tt> / <tt class="docutils literal"><span class="pre">(##)</span></tt> でのマッチに置き換わっていることだ.これらの意味はこの後の C-- の出力を見れば分かるだろう. <tt class="docutils literal"><span class="pre">-ddump-cmm</span></tt> で C-- の出力を見ると,以下のようになっている:</p>
<pre class="literal-block">
[main1_entry() // []
{ info_tbls: [(c1y24,
label: main1_info
rep: HeapRep static { Fun {arity: 1 fun_type: ArgSpec 3} }
srt: Nothing)]
stack_info: arg_space: 0 updfr_space: Nothing
}
{offset
c1y24: // global
if ((Sp + -8) < SpLim) (likely: False) goto c1y25; else goto c1y26;
c1y25: // global
R1 = main1_closure;
call (stg_gc_fun)(R1) args: 8, res: 0, upd: 8;
c1y26: // global
I64[Sp - 8] = block_c1y1Y_info;
R1 = GHC.Types.True_closure+2;
Sp = Sp - 8;
call stg_newMutVar#(R1) args: 8, res: 8, upd: 8;
}
},
section ""data" . main1_closure" {
main1_closure:
const main1_info;
},
_c1y1Y() // [R1]
{ info_tbls: [(c1y1Y,
label: block_c1y1Y_info
rep: StackRep []
srt: Nothing)]
stack_info: arg_space: 0 updfr_space: Nothing
}
{offset
c1y1Y: // global
call MO_WriteBarrier();
P64[R1 + 8] = GHC.Types.False_closure+1;
call "ccall" arg hints: [PtrHint,
PtrHint] result hints: [] dirty_MUT_VAR(BaseReg, R1);
R1 = P64[R1 + 8];
Sp = Sp + 8;
call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
}
}]
[main_entry() // []
{ info_tbls: [(c1y34,
label: main_info
rep: HeapRep static { Fun {arity: 1 fun_type: ArgSpec 3} }
srt: Nothing)]
stack_info: arg_space: 0 updfr_space: Nothing
}
{offset
c1y34: // global
call main1_info() args: 8, res: 0, upd: 8;
}
},
section ""data" . main_closure" {
main_closure:
const main_info;
}]
</pre>
<p>ちょっと長いけど,落ち着いて読めば大丈夫.まず, <tt class="docutils literal">main_entry</tt> の部分は見た通り <tt class="docutils literal">main1</tt> のクロージャを呼び出してるだけなのでいいだろう. STG で適用していたはずの <tt class="docutils literal">GHC.Prim.void#</tt> や受け取っていた <tt class="docutils literal">void_0E</tt> は完全に綺麗さっぱり消えていることがわかる.で, <tt class="docutils literal">main1_entry</tt> の方だが, C-- を読むに当たって以下のパターンを覚えておくと読みやすいと思う.</p>
<dl class="docutils">
<dt>スタックサイズチェック</dt>
<dd><pre class="first literal-block">
label_stackcheck: // global
if ((Sp + -8) < SpLim) (likely: False) goto label_ok; else goto label_gc;
label_gc: // global
R1 = main1_closure;
call (stg_gc_fun)(R1) args: 8, res: 0, upd: 8;
label_ok: // global
...
</pre>
<p class="last">クロージャエントリの最初などには,スタックの上限チェックが挟まる. <tt class="docutils literal">SpLim</tt> がスタックサイズの上限値を表していて,現在のスタックポインタがそれをオーバーしていないかチェックしている.スタックサイズが足りていないと,一旦 GC を走らせにいく.それでもオーバーするようなら stack overflow になる.</p>
</dd>
<dt>ヒープサイズチェック</dt>
<dd><pre class="first literal-block">
label_heapcheck: // global
Hp = Hp + N;
if (Hp > HpLim) (likely: False) goto label_gc; else goto label_ok;
label_gc: // global
HpAlloc = N;
R1 = R1;
call stg_gc_unpt_r1(R1) returns to label_heapcheck, args: 8, res: 8, upd: 8;
label_ok: // global
...
</pre>
<p class="last">今回は出てこないが,こちらもよくあるやつなので覚えておいたほうがいいと思う.ヒープ領域へのアロケーション時にヒープの上限チェックが挟まる. <tt class="docutils literal">HpLim</tt> がヒープサイズの上限値を表していて,確保する分 ( <tt class="docutils literal">N</tt> ) 足したヒープポインタがそれをオーバーしていないかチェックする.ヒープサイズが足りてないと,一旦 GC を走らせにいく.それでもオーバーするようなら heap overflow になる.なお,呼ぶ GC の関数は確保する領域に置かれるオブジェクトによって異なる.</p>
</dd>
<dt>サンク評価</dt>
<dd><pre class="first literal-block">
if (R1 & 7 != 0) goto label_ok; else goto label_eval;
label_eval: // global
call (I64[R1])(R1) returns to label_ok
label_ok: // global
...
</pre>
<p class="last">これも今回は出てないけど頻出のやつなので紹介しておく. GHC では pointer tagging という手法を使用していて,ポインタの下位 数 bit (うちは 64bit 環境でその場合 3 bit) はタグになっている <a class="footnote-reference" href="#heap-aligned" id="auto-id-5">[5]</a> .それぞれのタグの意味は <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/wikis/commentary/rts/haskell-execution/pointer-tagging">https://gitlab.haskell.org/ghc/ghc/wikis/commentary/rts/haskell-execution/pointer-tagging</a> を参照してもらうとして,大事なのは 0 の場合サンクを表すということ.上のコードはサンクかどうかを判定し,サンクならそのクロージャの評価に移る.そして,その後コードを実行する.</p>
</dd>
<dt>STG でのプリミティブ命令の変換</dt>
<dd><p class="first">今回, STG で呼び出していた <tt class="docutils literal">readMutVar#</tt> や <tt class="docutils literal">writeMutVar#</tt> はどっかへ行ってしまっている.影を残しているのは <tt class="docutils literal">newMutVar#</tt> のみでこいつも <tt class="docutils literal">stg_newMutVar#</tt> という名前になっている.実はプリミティブ命令は全てが全て RTS に関数として登録されているわけではない.多くは C-- の命令列に翻訳される.翻訳のされ方を調べる方法は,以下のことをすればいい:</p>
<ol class="arabic">
<li><p class="first">プリミティブ命令のコンストラクタを調べる.</p>
<p><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/compiler/prelude/primops.txt.pp">compiler/prelude/primops.txt.pp</a> を見にいく. <tt class="docutils literal">primtype</tt> / <tt class="docutils literal">primop</tt> が定義されている.名前の通り,プリミティブ型とプリミティブ命令を定義する部分. <tt class="docutils literal">primop</tt> は,</p>
<pre class="literal-block">
primop Constructor "identifier" Category Type
{Description.}
with attribute1 = value1 ...
</pre>
<p>という書式で書かれてる.見たいプリミティブ命令の identifier を検索して,対応する Constructor をまず調べる.</p>
</li>
<li><p class="first"><tt class="docutils literal">emitPrimOp</tt> の該当箇所を見にいく.</p>
<p><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/compiler/codeGen/StgCmmPrim.hs#L269">compiler/codeGen/StgCmmPrim.hs の emitPrimOp のパターンマッチ部分</a> を見にいく. <tt class="docutils literal">emitPrimOp</tt> はプリミティブ命令のコンストラクタをパターンマッチして,対応する C-- のコードを出す.最初に調べたコンストラクタで,パターンマッチの該当部分を見ればどういうコードが出されるかが分かる.</p>
</li>
</ol>
<p>例えば, <tt class="docutils literal">writeMutVar#</tt> は</p>
<pre class="literal-block">
primop WriteMutVarOp "writeMutVar#" GenPrimOp
MutVar# s a -> a -> State# s -> State# s
{Write contents of {\tt MutVar\#}.}
with
-- See Note [Why MutVar# ops can't fail]
has_side_effects = True
code_size = { primOpCodeSizeForeignCall } -- for the write barrier
</pre>
<p>と定義されている.なので対応するコンストラクタは <tt class="docutils literal">WriteMutVarOp</tt> になる.こいつの生成箇所は,</p>
<pre class="literal-block">
emitPrimOp dflags res@[] WriteMutVarOp [mutv,var]
= do -- Without this write barrier, other CPUs may see this pointer before
-- the writes for the closure it points to have occurred.
emitPrimCall res MO_WriteBarrier []
emitStore (cmmOffsetW dflags mutv (fixedHdrSizeW dflags)) var
emitCCall
[{-no results-}]
(CmmLit (CmmLabel mkDirty_MUT_VAR_Label))
[(baseExpr, AddrHint), (mutv,AddrHint)]
</pre>
<p>となっている.まさに, <tt class="docutils literal">main1_entry</tt> の</p>
<pre class="literal-block">
call MO_WriteBarrier();
P64[R1 + 8] = GHC.Types.False_closure+1;
call "ccall" arg hints: [PtrHint,
PtrHint] result hints: [] dirty_MUT_VAR(BaseReg, R1);
</pre>
<p>という部分が対応してる.なお,プリミティブ命令の一部は特殊で, <tt class="docutils literal"><span class="pre">out-of-line</span></tt> という属性を持ってたりする.今回は, <tt class="docutils literal">newMutVar#</tt> がこの属性を持っている:</p>
<pre class="literal-block">
primop NewMutVarOp "newMutVar#" GenPrimOp
a -> State# s -> (# State# s, MutVar# s a #)
{Create {\tt MutVar\#} with specified initial value in specified state thread.}
with
out_of_line = True
has_side_effects = True
</pre>
<p>この属性を持っているやつに関しては, <tt class="docutils literal">emitPrimOp</tt> では処理されず RTS に登録されている関数が使用される.その関数の中身は, <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/rts/PrimOps.cmm">rts/PrimOps.cmm</a> で定義されている.中身の識別子は <tt class="docutils literal">stg_</tt> という接頭辞をつけて Z エンコーディングされていて, <tt class="docutils literal">newMutVar#</tt> は,以下の実装が対応する:</p>
<pre class="last literal-block">
stg_newMutVarzh ( gcptr init )
{
W_ mv;
ALLOC_PRIM_P (SIZEOF_StgMutVar, stg_newMutVarzh, init);
mv = Hp - SIZEOF_StgMutVar + WDS(1);
SET_HDR(mv,stg_MUT_VAR_DIRTY_info,CCCS);
StgMutVar_var(mv) = init;
return (mv);
}
</pre>
</dd>
</dl>
<p>大体この 4 点を押さえておけば,なんとなくで読めると思う.出力された C-- のコードがやってることは,大体以下の感じ:</p>
<ol class="arabic simple">
<li>スタックサイズチェック</li>
<li>次の部分の継続をスタックに入れて, <tt class="docutils literal">GHC.Types.True</tt> を引数に <tt class="docutils literal">stg_newMutVar</tt> に移る.</li>
<li><tt class="docutils literal">stg_newMutVar</tt> から返ってきた <tt class="docutils literal">MutVar</tt> に <tt class="docutils literal">GHC.Types.False</tt> を書き込む.</li>
<li><tt class="docutils literal">MutVar</tt> から値を読み込む.</li>
<li>読み込んだ値を返り値として,スタックから次の継続を実行する.</li>
</ol>
<p>見ての通り,どこにも <tt class="docutils literal">State# RealWorld</tt> は現れない.しかも, <tt class="docutils literal">writeMutVar#</tt> の変換を部分を見れば分かるように,こいつは返り値が全く存在しない.ここから,</p>
<ul class="simple">
<li><tt class="docutils literal">Unit#</tt> は実行時表現を持たない (<tt class="docutils literal">newtype</tt> と同じ) .</li>
<li><tt class="docutils literal"><span class="pre">(##)</span></tt> と <tt class="docutils literal">GHC.Prim.void#</tt> は,完全に実行時表現を持たず,スタック・レジスタのいずれにも格納されない.</li>
</ul>
<p>ということが分かると思う. <tt class="docutils literal">State# RealWorld</tt> は STG の段階で実行時表現を持たない <tt class="docutils literal">GHC.Prim.void#</tt> へと変換され, C-- の段階ではコード中に片鱗すら見せない形に変換される.</p>
<p>なお余談だけど, unboxed proxy と呼ばれる <tt class="docutils literal">GHC.Prim.Proxy#</tt> 型も GHC では提供されていて,こいつは <tt class="docutils literal">State#</tt> と同じく <tt class="docutils literal">GHC.Prim.void#</tt> に変換され実行時には消えて無くなる.これを使って</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">type</span><span class="w"> </span><span class="kt">State</span><span class="o">#</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Proxy</span><span class="o">#</span>
</pre></div></td></tr></table></div>
<p>と定義しても同じ操作が起きる. <tt class="docutils literal">Proxy# a</tt> は unboxed なので,この型の値は関数で受け取る前に評価される:</p>
<pre class="literal-block">
>>> import GHC.Prim
>>> :set -XMagicHash
>>> f :: Proxy# a -> (); f _ = ()
>>> f undefined
*** Exception: Prelude.undefined
</pre>
<p>これは <tt class="docutils literal">State#</tt> でも同様.つまり, <tt class="docutils literal">State# RealWorld</tt> は実行時に消えるからといって何の影響も実行に及ぼさないというわけではないし,なんら特別な仕組みで動いているわけでもないということ. IO モナドは, unboxed な線形使用のサイズを持たない型と unboxed tuple を使って表現されることにより,結果の値を取り出すためパターンマッチをすると必ず <tt class="docutils literal">State# RealWorld</tt> は評価されるので,汎用的な unboxed の仕組みで評価タイミングを保証できることになる.なので,線形使用を守っているなら,特別な仕組みを必要とせず最適化やコード生成を行える.</p>
</div>
<div class="section" id="unsafe-io">
<h2>Unsafe IO<a class="headerlink" href="#unsafe-io" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal">State# RealWorld</tt> は直感的にはランタイムが内部で持っている外部情報を,仮想的に現実世界を表す状態とみたてた型で, <tt class="docutils literal">IO</tt> の評価タイミングを保証するものだった.そして,実際のコード生成では完全に削除され,保証された評価順序での実行コードだけが生成される.実行コードは無引数の関数コードとして保存され,ランタイムがメインスレッドで GC を立ち上げた後この関数コードを呼び出す.これが一連の流れになる.</p>
<p>ただ,上の流れは線形使用制約を守った使い方をする場合の話だった.では,制約を守らない場合はどうなるのだろうか? 上で紹介したコードについて同じように中間出力を見てみる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span></pre></div></td><td class="code"><div><pre><span></span><span class="cm">{-# LANGUAGE BlockArguments #-}</span>
<span class="cm">{-# LANGUAGE BangPatterns #-}</span>
<span class="cm">{-# LANGUAGE MagicHash #-}</span>
<span class="cm">{-# LANGUAGE UnboxedTuples #-}</span>
<span class="kr">import</span><span class="w"> </span><span class="nn">GHC.Base</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nf">\</span><span class="n">s0</span><span class="o">#</span><span class="w"> </span><span class="ow">-></span>
<span class="w"> </span><span class="kr">let</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unIO</span><span class="w"> </span><span class="p">(</span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"Hello"</span><span class="p">)</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unIO</span><span class="w"> </span><span class="p">(</span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"World"</span><span class="p">)</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>これは STG の段階では以下のようなコードになっていた:</p>
<pre class="literal-block">
main1 =
[] \r [void_0E]
case
GHC.IO.Handle.Text.hPutStr'
GHC.IO.Handle.FD.stdout
main4
GHC.Types.True
GHC.Prim.void#
of
{ Unit# ipv1_sRHj [Occ=Once!] ->
case ipv1_sRHj of {
() ->
case
GHC.IO.Handle.Text.hPutStr'
GHC.IO.Handle.FD.stdout
main2
GHC.Types.True
GHC.Prim.void#
of
{ Unit# ipv3_sRHn [Occ=Once!] ->
case ipv3_sRHn of { () -> Unit# [GHC.Tuple.()]; };
};
};
};
</pre>
<p>色々省略してるが,なんとなく出されたコードは分かるだろう. <tt class="docutils literal">main4</tt> は <tt class="docutils literal">"World"</tt> を表す文字列データ, <tt class="docutils literal">main2</tt> は <tt class="docutils literal">"Hello"</tt> を表す文字列データが格納されている. <tt class="docutils literal">GHC.IO.Handle.Text.hPutStr' :: Handle <span class="pre">-></span> String <span class="pre">-></span> Bool <span class="pre">-></span> IO ()</tt> は <tt class="docutils literal">putStrLn</tt> が最終的に参照する <tt class="docutils literal">base</tt> パッケージの関数で, 3 番目の引数に <tt class="docutils literal">True</tt> を渡すと,改行込みで文字列を出力する. <tt class="docutils literal">State# RealWorld</tt> を渡している部分は全て <tt class="docutils literal">GHC.Prim.void#</tt> に置き換わっており,返り値にいたっては <tt class="docutils literal">Unit# <span class="pre">[GHC.Tuple.()]</span></tt> を返すなどまるっきりの無視であり,制約を守らなくても特に特別な処理はされずやはり <tt class="docutils literal">State# RealWorld</tt> は実行時には完全に消えることが示唆されている.ただ,注目したいのは <tt class="docutils literal">hPutStr'</tt> の呼び出される順序で, <tt class="docutils literal">"World"</tt> が渡された後 <tt class="docutils literal">"Hello"</tt> が渡されていることが分かる.これが, <tt class="docutils literal">let</tt> で書いた順とは逆順に文字列が出力される原因である.</p>
<p>Haskell の仕様では let と case , BangPattern のセマンティクス <a class="footnote-reference" href="#let-semantics" id="auto-id-6">[6]</a> <a class="footnote-reference" href="#case-semantics" id="auto-id-7">[7]</a> <a class="footnote-reference" href="#bangpattern-semantics" id="auto-id-8">[8]</a> として,上から書いた順に評価されるのが基本だが,これらは副作用がないことが前提になっているので,最適化次第で順序を変えることができる.今回は逆順になっている.なお,明示的に以下のように <tt class="docutils literal">let</tt> を分けて書くとちゃんとした順序になる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">main</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">main</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nf">\</span><span class="n">s0</span><span class="o">#</span><span class="w"> </span><span class="ow">-></span>
<span class="w"> </span><span class="kr">let</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unIO</span><span class="w"> </span><span class="p">(</span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"Hello"</span><span class="p">)</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="kr">let</span>
<span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unIO</span><span class="w"> </span><span class="p">(</span><span class="n">putStrLn</span><span class="w"> </span><span class="s">"World"</span><span class="p">)</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s0</span><span class="o">#</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>ただこれももちろん最適化次第.線形使用制約を満たさないコードを書いても大体は直感的に動くけど,このように最適化やコード生成に影響する部分だと,直感に反する挙動をする場合がある.</p>
<p>さて, IO の動作は制約を守った上で,プログラムが操作順序をきちんと制御しながら書くのが理想だが,現実的には少し制約を破ってもパフォーマンスの改善やプログラミングを容易にしたいことがある.そのため, GHC ではこの制約を破る方法もいくつか提供されている.これが, <tt class="docutils literal">GHC.IO.Unsafe</tt> モジュールで提供されている関数群.主要なのは,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">unsafeDupablePerformIO</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">unsafeDupablePerformIO</span><span class="w"> </span><span class="p">(</span><span class="kt">IO</span><span class="w"> </span><span class="n">m</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">runRW</span><span class="o">#</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">of</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">unsafeDupableInterleaveIO</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="n">a</span>
<span class="nf">unsafeDupableInterleaveIO</span><span class="w"> </span><span class="p">(</span><span class="kt">IO</span><span class="w"> </span><span class="n">m</span><span class="p">)</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="p">(</span><span class="w"> </span><span class="nf">\</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">let</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="kr">of</span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="kr">_</span><span class="p">,</span><span class="w"> </span><span class="n">res</span><span class="w"> </span><span class="o">#</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">res</span>
<span class="w"> </span><span class="kr">in</span>
<span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">#</span><span class="p">))</span>
</pre></div></td></tr></table></div>
<p>の 2 つの関数. <tt class="docutils literal">runRW# :: (State# RealWorld <span class="pre">-></span> a) <span class="pre">-></span> a</tt> は <tt class="docutils literal"><span class="pre">ghc-prim</span></tt> パッケージの <tt class="docutils literal">GHC.Magic</tt> モジュールで定義されてる関数で,適当に <tt class="docutils literal">State# RealWorld</tt> を適用する関数. <tt class="docutils literal">GHC.Prim</tt> モジュールに <tt class="docutils literal">realWorld# :: State# RealWorld</tt> という値が定義されていて, <tt class="docutils literal">runRW# f = f realWorld#</tt> で定義されている.もちろん, <tt class="docutils literal">realWorld# = GHC.Prim.void#</tt> だ.</p>
<p><tt class="docutils literal">unsafeDupablePerformIO</tt> は, IO に <tt class="docutils literal">State# RealWorld</tt> を無理やり適用して結果を抽出する.つまり,副作用が起こる操作を無理やり実行するわけだ. <tt class="docutils literal">unsafeDupableInterleaveIO</tt> は <tt class="docutils literal">State# RealWorld</tt> を受け取ったもので適用するが,結果の状態は無視して元の状態を返す. <tt class="docutils literal">r</tt> はサンクになっていて, <tt class="docutils literal">r</tt> が評価された際初めて IO 操作が現在の IO 操作順序とは無関係に動き始める.特別な処理をしているわけではないが,感覚的には割り込みみたいなものだと思って良いと思う.</p>
<p>これら 2 つの関数は dupable と付いてる通り,マルチスレッドの場合一回だけ実行されるとは限らない.通常の副作用のない計算もそうだが,マルチスレッドの場合サンクはそれぞれのスレッドで評価される可能性がある.なお,マルチスレッドにおいてサンク評価をシングルスレッドに制限する方法も用意されていて, <tt class="docutils literal">GHC.Prim.noDuplicate# :: State# RealWorld <span class="pre">-></span> State# RealWorld</tt> がそう.こいつの本体は, <tt class="docutils literal">PrimOps.cmm</tt> の <tt class="docutils literal">stg_noDuplicatezh</tt> で,説明が <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/rts/PrimOps.cmm#L2188">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/rts/PrimOps.cmm#L2188</a> に書かれている.要点は,あるスレッドで <tt class="docutils literal">noDuplicate#</tt> が実行され,さらにもう一つのスレッドでも実行された場合もう一つの方はブロックされるということ.これを使って,通常使う API は定義されている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">unsafePerformIO</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">a</span>
<span class="nf">unsafePerformIO</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unsafeDupablePerformIO</span><span class="w"> </span><span class="p">(</span><span class="n">noDuplicate</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="n">m</span><span class="p">)</span>
<span class="nf">unsafeInterleaveIO</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="n">a</span>
<span class="nf">unsafeInterleaveIO</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">unsafeDupableInterleaveIO</span><span class="w"> </span><span class="p">(</span><span class="n">noDuplicate</span><span class="w"> </span><span class="o">>></span><span class="w"> </span><span class="n">m</span><span class="p">)</span>
<span class="nf">noDuplicate</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">noDuplicate</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">IO</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="nf">\</span><span class="n">s</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="kr">case</span><span class="w"> </span><span class="n">noDuplicate</span><span class="o">#</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="kr">of</span><span class="w"> </span><span class="n">s'</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="o">#</span><span class="w"> </span><span class="n">s'</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="w"> </span><span class="o">#</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>これにより,評価が始まると <tt class="docutils literal">noDuplicate</tt> が実行され単一スレッドでのみ評価が行われることになる. <tt class="docutils literal">unsafePerformIO</tt> は副作用をないものとして評価する関数で <tt class="docutils literal">Debug.Trace.trace</tt> で使われている. <tt class="docutils literal">unsafeInterleaveIO</tt> は <tt class="docutils literal">hGetContents</tt> など遅延 IO で使われていて, IO の皮を被っておきながら実際の操作は結果のサンクを評価した時に初めて実行されるというものだ.通常の IO はただの State モナドなので, IO の文脈で使われている限りインライン化しても問題ないわけだけだが, <tt class="docutils literal">unsafePerformIO</tt> は <tt class="docutils literal">State# RealWorld</tt> を適用して文脈外に値を取り出してしまうので,どこで評価が起きるかも保証されないし,内容によってはインライン展開のされ方によって副作用が何回か起きたりする場合もある. <tt class="docutils literal">Debug.Trace.trace</tt> を使ったことがある人は分かると思うが,文字列が出力されるタイミングは予測がかなり難しいし,インライン展開のされ方によって複数回出力がある場合もあればはじめの一回のみといったこともあり得る.</p>
<p>このように <tt class="docutils literal">State# RealWorld</tt> の線形使用を無視すると,便利なこともある反面,気をつけなければいけないことがかなり増える.副作用を持つ関数を遅延評価で扱うのはかなり骨が折れるし,その中で順序の保証を行えるようなデータ構造を与えているのに,そのデータ構造を無視する使い方をしてるわけだから当たり前といったらそうなのだけど.</p>
<p>とにかく, IO 自体は特別な仕組みを特に提供しておらず, unsafe な場合も例外ではない.特別な仕組みを提供する場合も <tt class="docutils literal">noDuplicate</tt> のようにプリミティブ操作を与えることで制御を行なっていることが分かる.</p>
</div>
<div class="section" id="st-io">
<h2>ST モナドと IO モナド<a class="headerlink" href="#st-io" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>IO モナドとよく一緒に語られるものとして ST モナドがある.こいつは,以下の定義になっている <a class="footnote-reference" href="#st-monad-definition" id="auto-id-9">[9]</a>:</p>
<pre class="literal-block">
newtype ST s a = ST (State# s -> (# State# s, a #))
</pre>
<p>IO と違うところは <tt class="docutils literal">State# RealWorld</tt> が <tt class="docutils literal">State# s</tt> と多相的になってるだけ.なので, <tt class="docutils literal">IO</tt> とは, <tt class="docutils literal">ST RealWorld</tt> のことだ.実際 <tt class="docutils literal">stToIO :: ST RealWorld a <span class="pre">-></span> IO a</tt> という命令も提供されている.</p>
<p>ST モナドは, <tt class="docutils literal">s</tt> が多相的なままで使われる. <tt class="docutils literal">GHC.Prim</tt> モジュールで提供されている API には <tt class="docutils literal">State# RealWorld</tt> を扱うものと <tt class="docutils literal">s</tt> を型パラメータとして <tt class="docutils literal">State# s</tt> を扱うものの 2 種類が提供されており,例えば <tt class="docutils literal">newMutVar#</tt> や <tt class="docutils literal">newArray#</tt> などは多相的なまま扱える.多くの場合重い命令やインライン展開されるとまずい命令などは <tt class="docutils literal">State# RealWorld</tt> で扱われ, <tt class="docutils literal">MutVar</tt> や <tt class="docutils literal">Array</tt> を扱うような軽く IO 処理が局所的に閉じられるような命令は多相的になっており,多相的になっている方が <tt class="docutils literal">ST</tt> モナドで使用できる.もちろん,多相パラメータを <tt class="docutils literal">RealWorld</tt> に特殊化してやれば IO と同様の操作もできる.</p>
<p>これらの多相的なプリミティブ命令のラッパとして, <tt class="docutils literal">Data.STRef</tt> や <tt class="docutils literal">array</tt> パッケージの <tt class="docutils literal">Data.Array.ST</tt> などが提供されており, <tt class="docutils literal">IORef</tt> や <tt class="docutils literal">IOArray</tt> は内部でこの <tt class="docutils literal">ST</tt> モナドの元で提供されてる API を <tt class="docutils literal">RealWorld</tt> で特殊化してさらにラップしてる.</p>
<p>ST モナドは多相的なまま保っている,つまり局所的に閉じられる処理のみ使っている場合は <tt class="docutils literal">runST :: (forall s. ST s a) <span class="pre">-></span> a</tt> で純粋な計算の中で計算可能だ.こいつは遅延しようがインライン展開されようが同じ処理を行い,現実世界にも見た目上特に影響を与えず <a class="footnote-reference" href="#runst-is-pure" id="auto-id-10">[10]</a> ,実行される. <tt class="docutils literal">RealWorld</tt> で特殊化された処理も入っている場合は <tt class="docutils literal">stToIO</tt> で IO に変換できる. <tt class="docutils literal">runST</tt> の実装がどうなってるかだが,次のようになっている:</p>
<pre class="literal-block">
runST :: (forall s. ST s a) -> a
runST (ST st_rep) = case runRW# st_rep of (# _, a #) -> a
</pre>
<p>ところで <tt class="docutils literal">GHC.Prim</tt> で定義されているデータ型の中にはパラメータに <tt class="docutils literal">s</tt> があるものもある. <tt class="docutils literal">runST</tt> では結果の型 <tt class="docutils literal">a</tt> は <tt class="docutils literal">s</tt> に依存しない必要があるので,このような型の値は <tt class="docutils literal">runST</tt> では外に出せないようになっている.例えば, <tt class="docutils literal">MutableByteArray# s</tt> は外に出せない.もしこいつが外に出せてしまったとすると,</p>
<pre class="literal-block">
arr :: MutableByteArray# s
arr = runST $ ST \s# -> newByteArray# 10 s#
update0Arr :: Int -> Int
update0Arr (I# i) = runST $ ST \s0# ->
let
!(# s1#, res# #) = readIntArray# arr 0# s0#
!s2# = writeIntArray# arr 0# i s1#
in (# s2#, I# res# #)
</pre>
<p>というプログラム (このプログラムは実際にはコンパイルエラーになる) で <tt class="docutils literal">update0Arr</tt> は前回書き込んだ値を返し,パラメータによって違う値を返してしまうことになる.このようなことを防ぐため,外に出してはいけないデータ型はパラメータ <tt class="docutils literal">s</tt> が付いている.このように, ST も IO と同じように特別なことはしておらず,既存の汎用的な仕組みを利用して,うまく実装されている <a class="footnote-reference" href="#runrw-magic" id="auto-id-11">[11]</a> .もちろん,コード生成も IO と同じように ST のラッパーが消え去って, <tt class="docutils literal">State# s</tt> も消え去ることになり,後は伝搬された <tt class="docutils literal">State# s</tt> の順序に従って評価順序が決定される.</p>
</div>
<div class="section" id="auto-id-12">
<h2>まとめ<a class="headerlink" href="#auto-id-12" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>GHC の IO についてちょっと調べた.実は, IOManager と RTS の内部の説明に行き着きたかったんだけど,長くなりそうなんで別途にすることにする.</p>
<p>なんとなくここら辺は知っていたんだけど,ここまで実際にコード生成見てみたことはなかったんで,色々知識が補強された.この辺結構賢いよなあって毎回思う.僕もこういうやつパッと思いつけるぐらい,強くなりてえなあ.</p>
<table class="docutils footnote" frame="void" id="io-monad-definition" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td><a class="reference external" href="http://hackage.haskell.org/package/ghc-prim-0.5.3/docs/src/GHC.Types.html#IO">http://hackage.haskell.org/package/ghc-prim-0.5.3/docs/src/GHC.Types.html#IO</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="how-to-defined-primtypes" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td>なお, <tt class="docutils literal">GHC.Prim</tt> の Haddock ドキュメントは全てダミー定義になっていて, <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/compiler/prelude/primops.txt.pp">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/compiler/prelude/primops.txt.pp</a> から生成されている.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="uniqueness-typing" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[3]</a></td><td>線形使用制約は,一意性とも呼ばれている.この制約を保証できる型システムを持ってる言語も,世の中にはいくつかある. Clean が有名だけど,最近だと Idris なども持っていて,一意型と言われる特殊な型を導入して,この型に関する検査で制約を検査する.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="ioref-use-mutvar-inside" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[4]</a></td><td><tt class="docutils literal">IORef</tt> は中で <tt class="docutils literal">MutVar#</tt> を使用している.本来なら,変換前のプログラムと完全に合わせるには,適宜コンストラクタで <tt class="docutils literal">MutVar#</tt> を包む操作が必要だが,ここではその部分は省略している.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="heap-aligned" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[5]</a></td><td>なお, <tt class="docutils literal">+ 8</tt> をスタックポインタにしている箇所が多いのはこのためで,ポインタはタグのため 8 byte ごとにしか番地を表せない.そのため,ヒープ領域もこのバイト数を単位に整地されていて, <tt class="docutils literal">+ 8</tt> は次の番地という意味になる.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="let-semantics" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[6]</a></td><td><a class="reference external" href="https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-450003.12">https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-450003.12</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="case-semantics" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[7]</a></td><td><a class="reference external" href="https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-610022">https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-610022</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="bangpattern-semantics" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-8">[8]</a></td><td><a class="reference external" href="https://downloads.haskell.org/~ghc/8.6.5/docs/html/users_guide/glasgow_exts.html#recursive-and-polymorphic-let-bindings">https://downloads.haskell.org/~ghc/8.6.5/docs/html/users_guide/glasgow_exts.html#recursive-and-polymorphic-let-bindings</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="st-monad-definition" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-9">[9]</a></td><td><a class="reference external" href="https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.ST.html#ST">https://hackage.haskell.org/package/base-4.12.0.0/docs/src/GHC.ST.html#ST</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="runst-is-pure" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-10">[10]</a></td><td>もちろん,スタックやヒープをいじることにはなるし, GC のお世話にもなるわけだけど,それは純粋な計算の場合も同じだ.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="runrw-magic" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-11">[11]</a></td><td>なお, <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/compiler/coreSyn/CorePrep.hs#L948">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.5-release/compiler/coreSyn/CorePrep.hs#L948</a> に書いてある通り,実は最適化によっては外に出てはいけないものが <tt class="docutils literal">runST</tt> の外に出てしまうことがある.なので,実際には <tt class="docutils literal">runST</tt> ,もとい <tt class="docutils literal">runRW#</tt> を最適化において特別扱いする必要がある.具体的には,インライン展開されるタイミングを他のものと比べずらしてるらしい.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/05/ghc-io-inside.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/05/ghc-io-inside.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Apache Spark についての覚書2019-05-12T13:29:06+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-05-12:/blog/posts/2019/05/cluster-distributed-programming/<p>ちょっと興味があったので, Apache Spark 関連についていくつか調べたことメモる.なお,僕は最近まで Apache Spark は MapReduce してると思っ …</p><p>ちょっと興味があったので, Apache Spark 関連についていくつか調べたことメモる.なお,僕は最近まで Apache Spark は MapReduce してると思ってたぐらいだし, Hadoop も Spark も触ったことない人間なんで,完全に信憑性はないです.そこはよろしく.</p>
<div class="section" id="auto-id-1">
<h2>分散処理の抽象<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Apache Spark 周りってほぼ歴史の話なんで,まずはそこから. Google の MapReduce から色々分散処理の抽象化が提唱されてきた.それぞれが Apache Spark の元になってるやつ.他にも色々あるっぽいけど,とりあえず目についたのをまとめてみた.</p>
<div class="section" id="mapreduce">
<h3>MapReduce<a class="headerlink" href="#mapreduce" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>Google が提案した技術で,最近の潮流の出所なんかな? 気持ちを知りたい時は, Google の有名な論文を読むのが正直早い気がするし,確実な気がする <a class="footnote-reference" href="#less-document-refered" id="auto-id-2">[1]</a> .以下のやつ:</p>
<blockquote>
Jeffrey, D., & Sanjay, G. (2004). MapReduce: simplified data processing on large clusters. In 6th OSDI 2004 (pp. 137–150). Retrieved from <a class="reference external" href="https://www.usenix.org/legacy/events/osdi04/tech/dean.html">https://www.usenix.org/legacy/events/osdi04/tech/dean.html</a></blockquote>
<p>論文と聞くと身構える人いるかもだけど,ページ数としては 13 ページで,かなり抽象化して大事な部分だけが書かれてるので,多分読みやすいと思う.特に 4 節だけでも読むのがいいかもしれない.これは, Apache Spark の構成知る上でも役に立つ知識だと思う.</p>
<p>基本的な考え方は簡単で,キーバリューペアの列に対して map / reduce の 2 種類の処理で分散処理プログラミングを行うというもの.例えば,よく使われるワードカウントの例だと,擬似コードになるけど,以下の感じ:</p>
<pre class="literal-block">
map(key: String, value: String):
for w in value.Words():
EmitIntermediate(key: w, value: "1")
reduce(key: String, values: Iterator<String>):
let result: Int = 0
for v in values:
result += ParseInt(v)
Emit(AsString(result))
</pre>
<p>この例は最初にドキュメントのパス名と内容の文字列が大量に与えられ,それに対して単語ごとの出現回数を数え出力することを想定している.やってることは大体想像つくと思うけど,</p>
<ol class="arabic simple">
<li>map 処理で各ドキュメントの文字列を単語ごとに区切り,それぞれ単語をキーとしてカウント 1 を中間出力する.</li>
<li>reduce で中間出力の各カウント結果を,単語ごとに合計して出力する.</li>
</ol>
<p>ここで,中間出力は 1 が出てくることは決まってるんだから, <tt class="docutils literal">result += ParseInt(v)</tt> なんて書かずに <tt class="docutils literal">result++</tt> って書けばいいじゃんって思う人がいるかもだけど,これは Combiner 最適化というものを想定しているため.これについては,後述する.</p>
<p>考え方だけだとこんな感じなんだけど,この実装をどうするかという問題があり,これについて上の論文で簡潔な説明と分かりやすい図が載ってるのでそこだけ紹介しておく.</p>
<a class="reference external image-reference" href="https://www.usenix.org/legacy/events/osdi04/tech/full_papers/dean/dean_html/index.html#fig:overview"><img alt="以下で説明される手順が,可視化されている." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/05/cluster-distributed-programming/cluster-distributed-programming/mapreduce-impl-image.png"/></a>
<p>まず,上の図を見れば分かると思うけど, MapReduce には 4 人登場人物がいる.それぞれ</p>
<dl class="docutils">
<dt>ユーザプログラム</dt>
<dd>通常 1 つで, map / reduce 処理及び入出力ファイルのフォーマットなどが書かれている.</dd>
<dt>マスターサーバ</dt>
<dd>通常 1 つで,ユーザプログラムを元にタスクを生成・管理する.</dd>
<dt>ワーカサーバ</dt>
<dd>たくさんあって,マスターサーバから割り当てられたタスクを忠実にこなす.</dd>
<dt>ストレージ</dt>
<dd>ワーカサーバ度に用意されていて,仮想的に分散ファイルシステムにより統合する形で構成されている.</dd>
</dl>
<p>となる.これらの登場人物が以下の処理を行うことで,全体の処理を完遂する:</p>
<ol class="arabic simple">
<li>ユーザプログラムは,入力 (デフォルトは,改行区切りで一列がキーバリューペア一個に相当するもの) を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span></span> 個に区切ってストレージに置いておく.次に,マスターサーバ,ワーカサーバが起動され,ユーザプログラムから,区切られた入力とそれをキーバリューペアにパースする方法, map / reduce の処理内容が与えられる.</li>
<li>マスターサーバは, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span></span> 個の map タスクを map 処理から, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span></span> 個の reduce タスクを reduce 処理から生成し,処理待ち状態のワーカサーバに割り当てていく.</li>
<li>map タスクが割り当てられたワーカサーバは,区切られた入力の中から自身のためのものを選び,パースして順に map 処理に投げていく.</li>
<li>map タスクが割り当てられたワーカサーバは,受け取った中間結果をローカルディスクに <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span></span> 個に区切って置いていく.この区切り方がポイントなんだけど,それについては後で.そして処理が終わったら,結果を置いた場所をマスターサーバに通知する.</li>
<li>reduce タスクが割り当てられたワーカサーバは,中間結果の場所を受け取ると,その場所をリモートアクセスで参照し,キーごとにまとめる.</li>
<li>reduce タスクが割り当てられたわーかサーバは,全ての中間結果を受け取ったら,加工した中間結果を reduce 処理になげ,出てきた結果を出力ファイルに追加する.</li>
<li>マスターサーバは全てのタスクが終了したら,ユーザプログラムに処理を戻す.</li>
</ol>
<p>なお, map タスクが生成した中間結果を, reduce タスクでキーごとにまとめる処理は,一般にシャッフルと呼ばれてるっぽい.大雑把には次のステップを行う:</p>
<dl class="docutils">
<dt>パーティション</dt>
<dd>map タスクはシャッフルの際,任意のキーに紐づくデータを 1 つの reduce タスクから参照できるように,中間結果を振り分ける必要がある.これは,例えばキーのハッシュ値の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi></mrow><annotation encoding="application/x-tex">R</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span></span> での剰余 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="normal">h</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">s</mi><mi mathvariant="normal">h</mi></mrow><mo stretchy="false">(</mo><mrow><mi>k</mi><mi>e</mi><mi>y</mi></mrow><mo stretchy="false">)</mo><mtext> </mtext><mo lspace="0.22em" rspace="0.22em"><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow></mo><mtext> </mtext><mi>R</mi></mrow><annotation encoding="application/x-tex">\mathrm{hash}(\mathit{key}) \bmod R</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">hash</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">key</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span></span> を振り分け先としてやれば,同じキーはハッシュ値が等しいため特に調整をしなくても同じ振り分け先となる.この処理はパーティションと呼ばれている.</dd>
<dt>ソート</dt>
<dd>中間結果をキーごとにまとめるために, reduce タスクはデータをソートする.こうすると,前から順に処理をしていけばキーが変わらない範囲がキーごとにまとまった範囲であることが分かる.この方法は,データが大量にありメモリに収まりきらない場合に,ソートにおいても範囲チェックにおいても対応が可能という点でこうしてるっぽい.</dd>
</dl>
<p>なお,この辺用語がいまいち分からないんだけど,資料によってシャッフルが指す範囲が変わることがあって,パーティションは含んだり含まなかったりもするので注意してほしい.</p>
<p>さて,クラスタベースの分散処理で一番ネックとなるのがネットワーク通信の部分だ.通信するデータを削減すれば,一般的にマシンパワーを改善するより劇的にパフォーマンスが変わる場合が多い. MapReduce では,大きなネットワーク通信を必要とするのがシャッフルを行うときだ.そこで reduce タスクに渡す前に map タスクの方で通信量を減らすための最適化手法, Combiner 最適化が知られている.これは, reduce タスクの実装パターンのよくある傾向を利用する.一般的に, reduce タスクは可換性と結合性を持つ演算で実装される場合が多い.つまり,部分的に先に計算して後からそれを総計する手法がとれる場合が多い.この部分的に先に計算する部分をユーザから追加で与えてもらい, map タスクが終わった後ワーカごとに処理する.そして,それをシャッフルにかける.この部分的に先に計算する処理が combiner と呼ばれる.先に出したワードカウントの例だと reduce の処理を combiner として設定することで, map タスクが終了したらシャッフル時にワーカ度のワード総計がまず行われ,その後その総計がパーティションされた後ソートされ,最終的にその値を元に全体の総計をとるといった流れになる. combiner 最適化はあくまで最適化なので,その適用方法は実装によって異なるし,もちろん combiner をかけることにより情報が欠落すると問題が起きる処理には適用できないので,この最適化が適用できるかはユーザ判断ということになる.ただ性能が劇的に改善する場合が多いので,割と一般的に使われてるようだ.</p>
</div>
<div class="section" id="pregel">
<h3>Pregel<a class="headerlink" href="#pregel" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>これもまた, Google が出所の技術で,やっぱり論文が出てるのでそれを読むのが良さそう:</p>
<blockquote>
Malewicz, G., Austern, M. H., Bik, A. J. ., Dehnert, J. C., Horn, I., Leiser, N., & Czajkowski, G. (2010). Pregel: A System for Large-Scale Graph Processing. In Proceedings of the 2010 international conference on Management of data - SIGMOD ’10 (p. 135). New York, New York, USA: ACM Press. <a class="reference external" href="https://doi.org/10.1145/1807167.1807184">https://doi.org/10.1145/1807167.1807184</a></blockquote>
<p>こっちも 11 ページぐらいなので,読んでみるのがいいと思うけど, MapReduce のよりちょっと読みにくいかも.</p>
<p>Pregel はグラフ処理の分散プログラミングに特化した抽象で,グラフが与えられた時にそれを分散処理してグラフを出力するプログラミングを支援する.考え方的には,グラフの頂点単位で処理を行わせ,メッセージ送受信で協調させることで,分散化を図るというもの.まずはどのようにプログラムを書くのかの例を見てもらった方が分かりやすいと思うので,擬似コードを挙げてみる.例えば,頂点に数値が割り当てられてる場合の,単一始点最短経路問題を解くプログラムは以下の感じになる:</p>
<pre class="literal-block">
const sourceId: VertexId = 0
compute(v: Vertex, msgs: Iterator<Message>):
let mindist: Int =
if v.Id() == sourceId then 0 else MaxInt()
for msg in msgs:
mindist = Min(mindist, msg.Value())
if mindist < v.Value():
for e in v.OutEdges():
SendMessageTo(
targetId: edge.TargetVertexId(),
value: mindist + e.Value(),
)
VoteToHalt()
</pre>
<p>このプログラムは,最終的に頂点番号 0 からの最短距離を各頂点が値として持つようなグラフを出力する.Pregel での処理内容は,大雑把には,</p>
<ol class="arabic simple">
<li>全ての頂点の状態を Active にする.</li>
<li>状態が Active な各頂点毎に compute を実行する.</li>
<li>全ての compute を実行しメッセージの送信を終えたら,全ての頂点の状態を更新する.</li>
<li>2 に戻る.</li>
</ol>
<p>を繰り返す.ここで特徴として,頂点は Active / InActive の 2 種類の状態を持ち,全ての頂点が InActive になれば自動的に処理が終わるようになっている.で,頂点状態の更新で状態は切り替わる.この切り替えの仕方は以下の手順で行われる.</p>
<ol class="arabic simple">
<li>VoteToHalt が compute で呼ばれていた場合, InActive になる.</li>
<li>メッセージを受信した場合, Active になる.</li>
</ol>
<p>なお, 2 は例え VoteToHalt が呼ばれたとしても,元々頂点が InActive で compute を実行していなくても,強制的に発動することに注意してほしい.で,分散処理なので MapReduce の時と同じくマスターとワーカがあり,マスターはグラフの頂点毎にタスクをワーカに発行するのが, Pregel モデルになる.</p>
<p>Pregel モデルの特徴は,同期にある.つまり,単純に頂点毎にタスクを発行してそれぞれ好き勝手に進めさせるのではなく, compute を実行する度に同期して一斉に頂点の状態更新を行いまたもう一度 compute を実行するという流れだ.これは元々バルク同期並列に着想を得たものらしく, Pregel モデルでもこの同期をバルク同期並列と呼んでいる.また,同期を挟むまでの一回の計算単位を 1 スーパーステップという単位で呼んでいる.メッセージの受信は同期を挟んだタイミングで行われ,あるスーパーステップではその前のスーパーステップで送信されたメッセージしか取り扱えない.このようなモデルにより,グラフ分散処理を実装に合わせながら,それなりに書きやすい抽象で提供している.</p>
<p>なお, <tt class="docutils literal">SendMessageTo</tt> は送り先の頂点番号が分かれば実際にはどの頂点にもメッセージを送れるのだが,送付先として情報が分かるのが隣接頂点ぐらいなので,自然処理は限られてくる.ただ,実際には全頂点で値を共有したいということがよくある.そこで,集約器 (aggregator) という仕組みも用意されていて,各頂点から値を受け取ってその値を演算して一つの値にし,その値を次のスーパーステップで参照できるようになっている.</p>
<p>また, Pregel モデルでも Combiner 最適化が有効で,メッセージをワーカ度に先にまとめてしまって,その後頂点でまとめたものをさらに処理することが問題なくできる場合に, combiner を追加することで性能を改善できる.最短経路の例だと以下の感じ:</p>
<pre class="literal-block">
const sourceId: VertexId = 0
compute(v: Vertex, msgs: Iterator<Message>):
let mindist: Int =
if v.Id() == sourceId then 0 else MaxInt()
for msg in msgs:
mindist = Min(mindist, msg.Value())
if mindist < v.Value():
for e in v.OutEdges():
SendMessageTo(
targetId: edge.TargetVertexId(),
value: mindist + e.Value(),
)
VoteToHalt()
#[combiner]
combine(msgs: Iterator<Message>, v: Vertex):
let mindist: Int = MaxInt()
for msg in msgs:
mindist = Min(mindist, msg.Value())
Emit(mindist)
</pre>
<p>これにより,メッセージはワーカの中で最小のものだけが送られるようになり,さらにそれぞれのワーカから送られたきたものの中から最小のものが compute で計算される.</p>
<p>なお, Pregel モデルは MapReduce に落とし込むことができ,単純に compute を map に,同期を reduce にすれば良い.一応,論文には実装のアウトラインも載っているが,そこまで目新しいことはないと思うので,こちらは割愛する.興味があれば読んでみてくれという感じ.</p>
</div>
<div class="section" id="auto-id-3">
<h3>分散ストリーム処理<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>分散ストリーム処理は,リアルタイムかつ継続性のある分散処理に特化した抽象.なんか一応出したけど,あんまり調べてない.とりあえず,文献だけ.</p>
<p>Google の実装である MillWheel の紹介</p>
<blockquote>
Akidau, T., Whittle, S., Balikov, A., Bekiroğlu, K., Chernyak, S., Haberman, J., … Nordstrom, P. (2013). MillWheel: fault-tolerant stream processing at internet scale. Proceedings of the VLDB Endowment, 6(11), 1033–1044. <a class="reference external" href="https://doi.org/10.14778/2536222.2536229">https://doi.org/10.14778/2536222.2536229</a></blockquote>
<p>Spark Streaming の仕組みの紹介</p>
<blockquote>
Zaharia, M., Das, T., Li, H., Hunter, T., Shenker, S., & Stoica, I. (2013). Discretized streams: fault-tolerant streaming computation at scale. In Proceedings of the Twenty-Fourth ACM Symposium on Operating Systems Principles - SOSP ’13 (pp. 423–438). New York, New York, USA: ACM Press. <a class="reference external" href="https://doi.org/10.1145/2517349.2522737">https://doi.org/10.1145/2517349.2522737</a></blockquote>
<p>Spark の Structured Streaming の仕組みの紹介</p>
<blockquote>
Armbrust, M., Das, T., Torres, J., Yavuz, B., Zhu, S., Xin, R., … Zaharia, M. (2018). Structured Streaming: A Declarative API for Real-Time Applications in Apache Spark. In Proceedings of the 2018 International Conference on Management of Data - SIGMOD ’18 (pp. 601–613). New York, New York, USA: ACM Press. <a class="reference external" href="https://doi.org/10.1145/3183713.3190664">https://doi.org/10.1145/3183713.3190664</a></blockquote>
<p>処理系を実装する際には,時間の整合性とか色々考えることがありそうだけど,実装された処理系を使う分には, MapReduce を使うにしろ他の抽象を使うにしろ,それほど大きくプログラミングスタイルは変わらないものが多いのかな.この辺は,触ってみないとなんとも言えなそう.</p>
</div>
</div>
<div class="section" id="auto-id-4">
<h2>Apache Spark について<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,それぞれの抽象にはそれにあった実装が,古今東西色々存在している. MapReduce の代表的なオープンソース実装としては Apache Hadoop MapReduce が有名だし, Pregel 実装としては Apache Giraph が有名だ.分散ストリーム処理は, Apache Storm があるのかな.まあ大半は Hadoop MapReduce 上の実装だったりするんだけど,それは置いておいて,元々 MapReduce はそれ自体がかなり用途を制限していて分散処理基盤としてもっと汎用的なものが欲しいという需要があったようだ.それを解決するため新たに MapReduce の代替として生み出されたのが, Apache Spark らしい.ただ,半分宣伝のためにメリットしか言ってないみたいなところもあって,実際にはかなり良し悪しがあるみたいだけど.</p>
<p>とりあえず,以下の文献にお世話になりながら,調べたことを書いておく.</p>
<ul class="simple">
<li><a class="reference external" href="https://spark.apache.org/docs/latest/rdd-programming-guide.html">https://spark.apache.org/docs/latest/rdd-programming-guide.html</a></li>
<li><a class="reference external" href="https://stanford.edu/~rezab/sparkclass/slides/itas_workshop.pdf">https://stanford.edu/~rezab/sparkclass/slides/itas_workshop.pdf</a></li>
<li><a class="reference external" href="https://github.com/JerryLead/SparkInternals">https://github.com/JerryLead/SparkInternals</a></li>
<li><a class="reference external" href="https://www.slideshare.net/AGrishchenko/apache-spark-architecture">https://www.slideshare.net/AGrishchenko/apache-spark-architecture</a></li>
</ul>
<div class="section" id="auto-id-5">
<h3>Apache Spark の構成<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>基本的に, Apache Spark は Hadoop 全体を塗り替えるものではなく, Hadoop のエコシステムのうち,分散処理エンジンの部分 Hadoop MapReduce の代替を目指すものっぽい.なので, Apache Spark は Hadoop のように分散ファイルシステムを持っていなくて,その代わり HDFS (Hadoop の分散ファイルシステム) が利用できるようになっている.また,クラスタマネージャは持ってるので自前で動かすこともできるが, Hadoop の YARN や Apache Mesos などでの管理にも対応してるっぽい.</p>
<p>ここら辺はちょっと使ったことがないので分からないが,一応 <a class="reference external" href="https://spark.apache.org/docs/latest/cluster-overview.html">公式のデプロイガイド</a> に書いてあるのを読む限りはそうっぽい.</p>
<p>Spark はそのまま生で使える DSL の他に,以下のライブラリを提供してる:</p>
<dl class="docutils">
<dt>Spark SQL</dt>
<dd><p class="first">SQL クエリで Spark を操作するための機構を提供する.</p>
<p class="last"><a class="reference external" href="https://spark.apache.org/docs/latest/sql-programming-guide.html">https://spark.apache.org/docs/latest/sql-programming-guide.html</a></p>
</dd>
<dt>Structured Streaming</dt>
<dd><p class="first">Spark SQL 上で分散ストリーム処理をするための機構を提供する.</p>
<p class="last"><a class="reference external" href="https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html">https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html</a></p>
</dd>
<dt>MLlib</dt>
<dd><p class="first">分散処理上での機械学習に特化した API を提供する.</p>
<p class="last"><a class="reference external" href="https://spark.apache.org/docs/latest/ml-guide.html">https://spark.apache.org/docs/latest/ml-guide.html</a></p>
</dd>
<dt>GraphX</dt>
<dd><p class="first">Pregel に対応したグラフ分散処理の機構を提供する.</p>
<p class="last"><a class="reference external" href="https://spark.apache.org/docs/latest/graphx-programming-guide.html">https://spark.apache.org/docs/latest/graphx-programming-guide.html</a></p>
</dd>
<dt>Spark Streaming</dt>
<dd><p class="first">分散ストリーム処理をするための機構を提供する.</p>
<p class="last"><a class="reference external" href="https://spark.apache.org/docs/latest/streaming-programming-guide.html">https://spark.apache.org/docs/latest/streaming-programming-guide.html</a></p>
</dd>
</dl>
</div>
<div class="section" id="auto-id-7">
<h3>Apache Spark のアーキテクチャ<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>Apache Spark は,内部はかなり複雑になっていて, MapReduce とか Pregel ほど単純ではない.ただ,プログラム自体はかなり自然に書けて,以下のようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">package</span><span class="w"> </span><span class="nn">example</span><span class="p">.</span><span class="n">spark</span>
<span class="k">import</span><span class="w"> </span><span class="nn">java</span><span class="p">.</span><span class="nn">util</span><span class="p">.</span><span class="nc">Random</span>
<span class="k">import</span><span class="w"> </span><span class="nn">org</span><span class="p">.</span><span class="nn">apache</span><span class="p">.</span><span class="nn">spark</span><span class="p">.</span><span class="n">_</span>
<span class="k">object</span><span class="w"> </span><span class="nc">SparkSample</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">def</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">args</span><span class="p">:</span><span class="w"> </span><span class="nc">Array</span><span class="p">[</span><span class="nc">String</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">numMappers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">100</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">numReducers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">50</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">numPairs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1000</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">numSize</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1000</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">sparkConf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">SparkConf</span><span class="p">().</span><span class="n">setAppName</span><span class="p">(</span><span class="s">"Spark Example"</span><span class="p">)</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">sc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">SparkContext</span><span class="p">(</span><span class="n">sparkConf</span><span class="p">)</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">pairs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">sc</span>
<span class="w"> </span><span class="p">.</span><span class="n">parallelize</span><span class="p">(</span><span class="mi">0</span><span class="w"> </span><span class="n">until</span><span class="w"> </span><span class="n">numMappers</span><span class="p">,</span><span class="w"> </span><span class="n">numMappers</span><span class="p">)</span>
<span class="w"> </span><span class="p">.</span><span class="n">flatMap</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">=></span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">ranGen</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">Random</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">arr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">Array</span><span class="p">[(</span><span class="nc">Int</span><span class="p">,</span><span class="w"> </span><span class="nc">Array</span><span class="p">[</span><span class="nc">Byte</span><span class="p">])](</span><span class="n">numPairs</span><span class="p">)</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o"><-</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="n">until</span><span class="w"> </span><span class="n">numPairs</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="n">byteArr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nc">Array</span><span class="p">[</span><span class="nc">Byte</span><span class="p">](</span><span class="n">numSize</span><span class="p">)</span>
<span class="w"> </span><span class="n">ranGen</span><span class="p">.</span><span class="n">nextBytes</span><span class="p">(</span><span class="n">byteArr</span><span class="p">)</span>
<span class="w"> </span><span class="n">arr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">ranGen</span><span class="p">.</span><span class="n">nextInt</span><span class="p">(</span><span class="nc">Int</span><span class="p">.</span><span class="nc">MaxValue</span><span class="p">),</span><span class="w"> </span><span class="n">byteArr</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">arr</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">.</span><span class="n">cache</span><span class="p">()</span>
<span class="w"> </span><span class="c1">// Enforce the calculation for cache</span>
<span class="w"> </span><span class="n">pairs</span><span class="p">.</span><span class="n">count</span><span class="p">()</span>
<span class="w"> </span><span class="n">println</span><span class="p">(</span><span class="n">pairs</span><span class="p">.</span><span class="n">groupByKey</span><span class="p">(</span><span class="n">numReducers</span><span class="p">).</span><span class="n">countByKey</span><span class="p">())</span>
<span class="w"> </span><span class="n">sc</span><span class="p">.</span><span class="n">stop</span><span class="p">()</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>Scala で書く場合,ほぼコレクション API と使い勝手が同じ感じになる. MapReduce ではそれぞれのタスクが自明にメソッド 1 つに対応してたけど, Spark の場合見ての通りメソッドチェーンで書かれていて,そこまで自明ではない.では,これがどのようにタスクに変換されるかだけど,大体以下の手順を通るらしい:</p>
<ol class="arabic simple">
<li>メソッドチェーンから論理プラン (データ依存グラフ) が作成される.</li>
<li>論理プランから物理プラン (有向非巡回グラフ) が作成される.</li>
<li>物理プランを元にタスクを生成し,ワーカに割り当て実行する.</li>
</ol>
<p>上のコードを例に,それぞれのやってることを大雑把に書いておく.</p>
<p>まずは Spark のプログラミングの基本から. Spark の処理メソッドは, <a class="reference external" href="https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.rdd.RDD">RDD (Resilient Distributed Dataset)</a> と呼ばれるオブジェクトを返してくる.上の例だと</p>
<ul class="simple">
<li><tt class="docutils literal">parallelize</tt></li>
<li><tt class="docutils literal">flatMap</tt></li>
<li><tt class="docutils literal">groupByKey</tt></li>
</ul>
<p>がそれぞれ RDD オブジェクトを返す.見ての通り, RDD オブジェクトは連鎖させることができ,入力から RDD を生成するメソッドと RDD オブジェクトを元に RDD オブジェクトを生成するものが存在する. RDD を連鎖によって生成した場合,その連鎖はオブジェクトに記録されている.ただ,注意して欲しいのは,メソッド 1 つに RDD 一つが必ずしも紐づくとは限らず, <tt class="docutils literal">groupByKey</tt> は 2 つの RDD を連鎖させる.これについては,後述する.なお, Spark ではこのような RDD オブジェクトを生成するメソッドは全て遅延され,特にタスクが生成されることはないしファイルが読み込まれたりすることもない.このようなメソッドは,変換 (transformation) と呼ばれてるらしい.</p>
<p>逆に, RDD 以外の結果だったり <tt class="docutils literal">Unit</tt> だったりを返してくるメソッドも存在する.上の例だと</p>
<ul class="simple">
<li><tt class="docutils literal">count</tt></li>
<li><tt class="docutils literal">countByKey</tt></li>
</ul>
<p>がそう.こいつらが呼ばれると初めてタスクの振り分け・実行が行われる.この辺は O/R マッパーとかと同じ.これをアクション (action) と呼ぶ.</p>
<p>生成される RDD は変換ごとに異なる.変換の処理内容によってもそうなのだが,主に元となった RDD の結果がどう生成した RDD に依存しているかが,論理プランを決めるとき重要になる.さて, Spark では MapReduce と同じように入出力データはいくつかの区分に区切られている.これをパーティション (partition) と呼ぶ.それぞれの RDD では異なるパーティション構成が用いられる. RDD のデータ依存関係とは出力する RDD (親 RDD) のパーティションとそれを受け取る RDD (子 RDD) のパーティションがどのように依存しあってるかを表す関係である.論理プランは,このパーティションを頂点としてデータ依存関係を辺とするデータ依存グラフになる.なお今回出していないが,親 RDD は 1 つの子 RDD に対し複数ある場合もあって, <tt class="docutils literal">join</tt> / <tt class="docutils literal">union</tt> などのオペレータはそういう子 RDD を作る.</p>
<p>Spark のデータ依存関係は大きく 2 種類ある <a class="footnote-reference" href="#general-data-dependency" id="auto-id-8">[2]</a> :</p>
<dl class="docutils">
<dt>限定依存 (narrow dependency)</dt>
<dd>親 RDD のパーティションは全て,高々 1 つの子 RDD のパーティションに依存する.</dd>
<dt>広域依存 (shuffle dependency / wide dependency)</dt>
<dd>親 RDD のパーティションに対し,子 RDD の複数のパーティションが紐づく場合がある.</dd>
</dl>
<p>この依存関係の違いは,シャッフルが必要あるかないかで,限定依存はシャッフルが必要ないため依存関係がネットワーク越しにならないようタスクを振り分ければ速く処理できるが,広域依存はシャッフルが必要になる.</p>
<ul class="simple">
<li><tt class="docutils literal">map</tt> は入力と出力が 1 対 1 対応してるので限定依存</li>
<li><tt class="docutils literal">groupByKey</tt> は一般にどのキーがどのパーティションに含まれるか,実行前に判別することは難しいので,広域依存扱い</li>
</ul>
<p>という感じになる.上のプログラムだと以下の論理プランが生成されるっぽい:</p>
<img alt="flatMap は限定依存, groupByKey は広域依存になる." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/05/cluster-distributed-programming/cluster-distributed-programming/example-logical-plan.png"/>
<p>点線は RDD を,実線はパーティションを表している.それぞれの RDD は</p>
<dl class="docutils">
<dt>ParallelCollection</dt>
<dd><tt class="docutils literal">parallelize</tt> に対応し,指定された数だけパーティションを作る.</dd>
<dt>FlatMapped</dt>
<dd><tt class="docutils literal">flatMap</tt> に対応し,親 RDD のパーティションの数だけパーティションを作る.</dd>
<dt>Shuffled</dt>
<dd><tt class="docutils literal">groupByKey</tt> の前処理に対応し,シャッフルして指定された数だけパーティションを作り,同じキーを持つ要素をかき集める.</dd>
<dt>MapPartitions</dt>
<dd><tt class="docutils literal">groupByKey</tt> の後処理に対応し,この RDD 自体はパーティションごとに変換を行う.今回は同じキーを持つ要素を一つの要素にまとめる.</dd>
</dl>
<p>みたいな感じになる.</p>
<p>論理プランは以上の感じでデータ依存グラフを作る.この論理プランを元に,実際の実行フローに合わせたグラフ,物理プランが作られる.物理プランは以下の手順で作られる,タスクを頂点として,変換を辺としたグラフになる:</p>
<ol class="arabic">
<li><p class="first">まず,論理プランを部分グラフに分けるらしい.この部分グラフをステージと呼ぶ.</p>
<p>なお,ステージの分け方としては大雑把に言えば,出力から逆向きに辿り広域依存を区切りに分けるらしい.</p>
</li>
<li><p class="first">ステージそれぞれで最後の RDD のパーティションごとにタスクを生成する.</p>
<p>ステージがアクション結果を生成するなら result タスク,それ以外の場合 shuffle-map タスクを割り当てる.shuffle-map タスクは生成結果にシャッフルを必要とする.</p>
</li>
</ol>
<p>上のプログラムだと以下の物理プランが生成されるっぽい:</p>
<img alt="ステージは出力から逆順にナンバリングされていく." class="align-center" src="https://mizunashi-mana.github.io/blog/posts/2019/05/cluster-distributed-programming/cluster-distributed-programming/example-physical-plan.png"/>
<p>赤線が shuffle-map タスク,青線が result タスクになる.ステージもタスクも,出力側から見て区切っていくけど,グラフ自体は入力側から辺が張られるのかな? この辺ちょっと分からなかったので,辺は書かなかった.まあ,こんな感じのが出来上がるっぽい.</p>
<p>後は,入力側のステージのタスクから,各ステージごとに順に実行していくみたい.そろそろ疲れたきたので,今日はこの辺で.</p>
</div>
</div>
<div class="section" id="auto-id-9">
<h2>まとめ<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ここらへん話聞くだけでかなり知らない領域だったので,実際に調べてみて結構色々知れたのは良かったと思う.ただ,キャッシュの仕組みとかシャッフルの仕組みにも Hadoop での経験を生かした工夫があるらしく,そこら辺ちょっと調べきれてないので,また時間があったら調べてみたい.後, Spark をすぐ起動できる Docker イメージとかあるっぽいので,近いうちに触ってみようかなと思った. Spark は spark shell とかいう対話式でプログラム実行できるやつがあるらしく,結構色々充実してそう.後, Spark SQL とか Hive とかは中で SQL を RDD や MapReduce に変換してるらしく <a class="footnote-reference" href="#sql-to-rdd" id="auto-id-10">[3]</a> ,その辺の仕組みとかもちょっと興味があるので調べてみたい.</p>
<p>ま,気が向いたらその辺の記事とかも書くかもねってことで,以上.</p>
<table class="docutils footnote" frame="void" id="less-document-refered" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>あんまり文献読んでない人並みの感想</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="general-data-dependency" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-8">[2]</a></td><td>なお,違う定義の分け方もあるらしく,この辺の用語はちょっと怪しいかも.まあ重要なのは用語ではなく,なぜこの分け方をするかなので,今回はシャッフルが自明に必要あるかないかで分ける定義を採用した. Spark 内部で実際どの種類分けがされているかは調べた方が良さそうと思って調べてない.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="sql-to-rdd" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-10">[3]</a></td><td>まあ単純に SQL パースして, JOIN とか GROUP BY はシャッフルを入れたりして,対応する変換を出力するとかっぽいけど.ただそれが分かると,Spark や Hadoop 上で SQL 実行する時のパフォーマンス予想とかできそうで,役に立ちそうでもある.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/05/cluster-distributed-programming.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/05/cluster-distributed-programming.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Sentry でエラー監視2019-05-02T07:43:30+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-05-02:/blog/posts/2019/05/add-sentry-monitoring/<p>クロスプラットフォームのエラー監視を行う Sentry というサービスがある.ブログに試しに導入してみたので,それにつ …</p><p>クロスプラットフォームのエラー監視を行う Sentry というサービスがある.ブログに試しに導入してみたので,それについて書く.</p>
<div class="section" id="auto-id-1">
<h2>Sentry について<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Sentry は,提供されている SDK を PHP コードや JavaScript コードに埋め込むことで,エラーを Sentry に送り,管理画面から確認できるようにするサービスだ.コードが <a class="reference external" href="https://github.com/getsentry/sentry">https://github.com/getsentry/sentry</a> で公開されていて,オンプレでも動かせる. <a class="reference external" href="https://sentry.io/">https://sentry.io/</a> にデプロイされていて,今回はそれを使っている.</p>
<p>例えば JavaScript でエラーが取れると,以下のような情報が見れる <a class="footnote-reference" href="#hide-ip-address" id="auto-id-2">[1]</a>:</p>
<img alt="Sentry の Web画面では,エラーが起きた IP / User-Agent などを見れる." src="https://mizunashi-mana.github.io/blog/posts/2019/05/add-sentry-monitoring/add-sentry-monitoring/sentry-web-image.png"/>
<p>管理画面ではエラーを共有したり,コメントをつけたり,似たエラーを見れたり,色々充実してる.今回は使用していないが,ユーザーにフィードバックを求めるダイアログを表示し,そのフィードバックを管理したりもできる.</p>
<p>内部の仕組みは,詳しく見てないけど, JavaScript の場合 <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror">window.onerror</a> とかで監視してるっぽい?</p>
</div>
<div class="section" id="auto-id-3">
<h2>Sentry の導入<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>では, Sentry を導入してみる.と言っても,そこまで複雑なことをする必要はなくて,大体以下の手順をやればいい:</p>
<ol class="arabic simple">
<li>(アカウントが無ければ) <a class="reference external" href="https://sentry.io/">https://sentry.io/</a> に Sign Up する.</li>
<li>プロジェクトを作る.</li>
<li>SDK をインストールする.</li>
<li>セキュリティトークンを入手し,設定する.</li>
</ol>
<p>アカウントを作ると,プロジェクト作成画面に移るので,監視したいプロジェクトの種類を選択し,名前を入力してプロジェクト作成を行う.後は,</p>
<pre class="literal-block">
npm install -D @sentry/browser
</pre>
<p>して, Installing Instructions からセキュリティートークンを入手し,書いてある通りに設定する:</p>
<pre class="literal-block">
import * as Sentry from "@sentry/browser";
Sentry.init({
dsn: 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@sentry.io/xxxxxxx',
});
</pre>
<p>試しに,エラーを起こしてちゃんと情報が取れるか確認してみると良い:</p>
<pre class="literal-block">
setTimeout(() => { throw new Error("sample error"); }, 0);
</pre>
<p>これで,管理画面の Issues にエラーが表示されれば大丈夫.</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まだ本格的に使い始めて無いので,使い勝手は分からないけど,色々便利そうではある.</p>
<p>世の中色々便利なサービスはあるんだなあって感じだ.こういうの使ってみないと知見溜まらないしね.そういう感じで.</p>
<table class="docutils footnote" frame="void" id="hide-ip-address" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>IP アドレスは隠してる.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/05/add-sentry-monitoring.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/05/add-sentry-monitoring.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>CPO に関連する定義まとめ2019-05-01T16:25:27+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-05-01:/blog/posts/2019/05/cpo-related-definitions/<p>某勉強会がコーヒーブレイクタイムに入って,ブレイクタイムから抜けたら何もかも忘れてそうだったので,数式レ …</p><p>某勉強会がコーヒーブレイクタイムに入って,ブレイクタイムから抜けたら何もかも忘れてそうだったので,数式レンダリングのテストも兼ねて CPO 関連の定義だけまとめておくことにした.</p>
<p>なお各定義は, SoPL (Semantics of Programming Languages) に則ってる.</p>
<div class="section" id="complete-partial-order">
<h2>Complete Partial Order<a class="headerlink" href="#complete-partial-order" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まあ,まずはおなじみのやつから.</p>
<dl class="docutils">
<dt>定義. 半順序 (partially ordered set, poset, partial order)</dt>
<dd><p class="first">集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> と二項関係 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mo stretchy="false">(</mo><mo>⊑</mo><mo stretchy="false">)</mo></mrow><mo>⊆</mo><mi>D</mi><mo>×</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">{(\sqsubseteq)} \subseteq D \times D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mopen">(</span><span class="mrel">⊑</span><span class="mclose">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> の組 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⟨</mo><mi>D</mi><mo separator="true">,</mo><mo>⊑</mo><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\langle D, \sqsubseteq\rangle</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">⟩</span></span></span></span></span> で,以下の制約を満たすもの:</p>
<dl class="last docutils">
<dt>反射律 (reflexive)</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mi>x</mi><mo>⊑</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">\forall x \in D\ldotp x \sqsubseteq x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></dd>
<dt>反対称律 (anti-symmetric)</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mo stretchy="false">(</mo><mi>x</mi><mo>⊑</mo><mi>y</mi><mo>∧</mo><mi>y</mi><mo>⊑</mo><mi>x</mi><mo stretchy="false">)</mo><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mi>x</mi><mo>=</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">\forall x, y \in D\ldotp (x \sqsubseteq y \land y \sqsubseteq x) \implies x = y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></dd>
<dt>推移律 (transitive)</dt>
<dd><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo separator="true">,</mo><mi>z</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mo stretchy="false">(</mo><mi>x</mi><mo>⊑</mo><mi>y</mi><mo>∧</mo><mi>y</mi><mo>⊑</mo><mi>z</mi><mo stretchy="false">)</mo><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mi>x</mi><mo>⊑</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">\forall x, y, z \in D\ldotp (x \sqsubseteq y \land y \sqsubseteq z) \implies x \sqsubseteq z</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></span></dd>
</dl>
</dd>
</dl>
<p>なお,二項関係が文脈から分かる場合単に集合を poset と呼んだり,逆に集合が分かる場合二項関係を半順序と呼んだりする.二項関係がどの poset のものか示すため, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>⊑</mo><mi>D</mi></msub></mrow><annotation encoding="application/x-tex">\sqsubseteq_D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mrel"><span class="mrel">⊑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">D</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> と書いたりもする.total な関係になっていれば,全順序.</p>
<dl class="docutils">
<dt>定義. (上に) 有界 (bounded (above), consistent)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> に対して,その部分集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo>⊆</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">P \subseteq D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が (上に) 有界とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∃</mi><mi>x</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mi mathvariant="normal">∀</mi><mi>y</mi><mo>∈</mo><mi>P</mi><mo separator="true">.</mo><mi>y</mi><mo>⊆</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">
\exists x \in D\ldotp \forall y \in P\ldotp y \subseteq x
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∃</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></div>
<p class="last">この時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> の上界 (an upper bound) と呼ぶ.</p>
</dd>
</dl>
<p>なお,普通 bounded は上下に有界な時使う気がするけど,この後は特に断りない限り, bounded above のことを有界と言っていく.後逆は, bounded below と lower bound .それと, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mi>x</mi><mi>n</mi></msub><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\{x_1, \ldots, x_n\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span></span> が有界な時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mn>1</mn></msub><mo>↑</mo><mo>⋯</mo><mo>↑</mo><msub><mi>x</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">x_1 \uparrow \cdots \uparrow x_n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> と書く.組になってる時は, consistency pair と呼んだりもするっぽい.</p>
<dl class="docutils">
<dt>定義. 上限 (least upper bound, lub, supremum, sup)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> ,その有界集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo>⊆</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">P \subseteq D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> に対して,その上界 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⨆</mo><mi>P</mi><mo>∈</mo><mi>P</mi></mrow><annotation encoding="application/x-tex">\bigsqcup P \in P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> が上限とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mtext>任意の上界 </mtext><mstyle displaystyle="false" scriptlevel="0"><mi>x</mi></mstyle><mtext> について</mtext></mrow><mtext> </mtext><mo>⨆</mo><mi>P</mi><mo>⊑</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">
\text{任意の上界 \(x\) について}\,\bigsqcup P \sqsubseteq x
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mord text"><span class="mord cjk_fallback">任意の上界</span><span class="mord"> </span><span class="mord mathnormal">x</span><span class="mord"> </span><span class="mord cjk_fallback">について</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></div>
</dd>
</dl>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo><mrow><mi mathvariant="normal">s</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">p</mi></mrow></mo><mi>P</mi><mo>=</mo><mo>⨆</mo><mi>P</mi></mrow><annotation encoding="application/x-tex">\mathop{\mathrm{sup}} P = \bigsqcup P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mop"><span class="mord"><span class="mord mathrm">sup</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> という記法や, pointwise に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>⨆</mo><mrow><mi>x</mi><mo>∈</mo><mi>P</mi></mrow></msub><mi>x</mi><mo>=</mo><mo>⨆</mo><mi>P</mi></mrow><annotation encoding="application/x-tex">\bigsqcup_{x \in P} x = \bigsqcup P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0771em;vertical-align:-0.3271em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1786em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3271em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> ,<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo><mrow><mi mathvariant="normal">s</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">p</mi></mrow></mo><mrow><mi>x</mi><mo>∈</mo><mi>P</mi></mrow></msub><mi>x</mi><mo>=</mo><mo><mrow><mi mathvariant="normal">s</mi><mi mathvariant="normal">u</mi><mi mathvariant="normal">p</mi></mrow></mo><mi>P</mi></mrow><annotation encoding="application/x-tex">\mathop{\mathrm{sup}}_{x \in P} x = \mathop{\mathrm{sup}} P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7021em;vertical-align:-0.2715em;"></span><span class="mop"><span class="mop"><span class="mord"><span class="mord mathrm">sup</span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2342em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2715em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mop"><span class="mord"><span class="mord mathrm">sup</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> という記法を使うこともある.また, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mn>1</mn></msub><mo>⊔</mo><mo>⋯</mo><mo>⊔</mo><msub><mi>x</mi><mi>n</mi></msub><mo>=</mo><mo>⨆</mo><mo stretchy="false">{</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mi>x</mi><mi>n</mi></msub><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">x_1 \sqcup \cdots \sqcup x_n = \bigsqcup \{x_1, \ldots, x_n\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span></span> と書くこともある.</p>
<p>上限の中で一番小さいやつ.全ての有界集合が sup 持つとは限らない (上界同士で上下関係がないことがあるので) ことに注意.存在すれば一意に決まる.逆は, greatest lower bound (glb) または infimum (inf) .</p>
<dl class="docutils">
<dt>定義. 有向部分集合 (directed subset)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> に対して,その部分集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>⊆</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">M \subseteq D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が有向とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>U</mi><mo>∈</mo><msub><mi mathvariant="script">P</mi><mrow><mi>f</mi><mi>i</mi><mi>n</mi></mrow></msub><mo stretchy="false">(</mo><mi>M</mi><mo stretchy="false">)</mo><mo separator="true">.</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mi>U</mi></mstyle><mtext> は上界 </mtext><mstyle displaystyle="false" scriptlevel="0"><mi>x</mi><mo>∈</mo><mi>P</mi></mstyle><mtext> を持つ</mtext></mrow></mrow><annotation encoding="application/x-tex">
\forall U \in \mathcal{P}_{\mathit{fin}}(M)\ldotp \text{\(U\) は上界 \(x \in P\) を持つ}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0822em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathit mtight">fin</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose">)</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mord"> </span><span class="mord cjk_fallback">は上界</span><span class="mord"> </span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord"> </span><span class="mord cjk_fallback">を持つ</span></span></span></span></span></span></div>
</dd>
</dl>
<p>名前の意味的には,部分集合の上界を集めるとまたそれに上界があり,それにもやっぱり上界があってと言う感じで,最終的にある場所に対して上に上に順序が伸びていく感じ.なお,伸びていく場所が 2 点とか 3 点になってるような奴は, directed にならない.あと空集合にも上界の存在を求めてるので,空集合自体は directed じゃないことにも注意.また, directed subset は自身の内に上限を持つとは限らなくて, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><mo stretchy="false">)</mo><mo>⊆</mo><mi mathvariant="double-struck">R</mi></mrow><annotation encoding="application/x-tex">[0,1) \subseteq \mathbb{R}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">R</span></span></span></span></span> を考えてみると,こいつは poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⟨</mo><mi mathvariant="double-struck">R</mi><mo separator="true">,</mo><mo>≤</mo><mo stretchy="false">⟩</mo></mrow><annotation encoding="application/x-tex">\langle \mathbb{R}, \leq\rangle</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord mathbb">R</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mclose">⟩</span></span></span></span></span> の directed subset になってて,上限は 1 だが,これは自身の内にはない.</p>
<dl class="docutils">
<dt>定義. 完備半順序 (complete partial order, cpo)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が,完備であるとは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>任意の directed subset </mtext><mstyle displaystyle="false" scriptlevel="0"><mi>P</mi><mo>⊆</mo><mi>D</mi></mstyle><mtext> は sup を持つ</mtext></mrow><annotation encoding="application/x-tex">
\text{任意の directed subset \(P \subseteq D\) は sup を持つ}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord text"><span class="mord cjk_fallback">任意の</span><span class="mord"> directed subset </span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord"> </span><span class="mord cjk_fallback">は</span><span class="mord"> sup </span><span class="mord cjk_fallback">を持つ</span></span></span></span></span></span></div>
</dd>
</dl>
<p>directed subset は,有限の場合 sup を中に持つ.なので,有限 poset は cpo になる.cpo でない例としては,自然数の集合に通常の順序 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\leq</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span></span> をいれた poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi><mo>=</mo><mo stretchy="false">{</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><mo separator="true">,</mo><mo>…</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\omega = \{0, 1, \ldots\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mclose">}</span></span></span></span></span> とか. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span> は自身の directed subset になるが,その上限は存在しない.で, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>ω</mi><mi mathvariant="normal">∞</mi></msub><mo>=</mo><mi>ω</mi><mo>∪</mo><mo stretchy="false">{</mo><mi mathvariant="normal">∞</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\omega_{\infty} = \omega \cup \{\infty\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">∞</span><span class="mclose">}</span></span></span></span></span> に拡張して <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∞</mi></mrow><annotation encoding="application/x-tex">\infty</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">∞</span></span></span></span></span> を最大要素となるよう順序も拡張すると,こいつは cpo になる.</p>
<dl class="docutils">
<dt>定義. 点付き (pointed)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が点付きであるとは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∃</mi><mi mathvariant="normal">⊥</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mi mathvariant="normal">∀</mi><mi>x</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mi mathvariant="normal">⊥</mi><mo>⊑</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">
\exists \bot \in D\ldotp \forall x \in D\ldotp \bot \sqsubseteq x
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∃⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">⊥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></div>
</dd>
</dl>
</div>
<div class="section" id="auto-id-1">
<h2>CPO の性質<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>こっちもおなじみのやつ.</p>
<dl class="docutils">
<dt>定義. 単調 (monotone)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi></mrow><annotation encoding="application/x-tex">E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> への関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi>D</mi><mo>→</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">f: D \to E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> が単調とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mi>x</mi><mo>⊑</mo><mi>y</mi><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>⊑</mo><mi>f</mi><mo stretchy="false">(</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\forall x, y \in D\ldotp x \sqsubseteq y \implies f(x) \sqsubseteq f(y)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7194em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></div>
</dd>
</dl>
<p>順序を保存する関数.流石に順序ぐらいは保存してくれないとね.</p>
<dl class="docutils">
<dt>定義. 連続 (continuous)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi></mrow><annotation encoding="application/x-tex">E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> への単調関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi>D</mi><mo>→</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">f: D \to E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> が連続とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mtext>任意の directed subset </mtext><mstyle displaystyle="false" scriptlevel="0"><mi>P</mi><mo>⊆</mo><mi>D</mi></mstyle><mtext> について</mtext></mrow><mtext> </mtext><mi>f</mi><mo stretchy="false">(</mo><mo>⨆</mo><mi>P</mi><mo stretchy="false">)</mo><mo>=</mo><munder><mo>⨆</mo><mrow><mi>x</mi><mo>∈</mo><mi>P</mi></mrow></munder><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\text{任意の directed subset \(P \subseteq D\) について}\, f(\bigsqcup P) = \bigsqcup_{x \in P} f(x)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mord text"><span class="mord cjk_fallback">任意の</span><span class="mord"> directed subset </span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord"> </span><span class="mord cjk_fallback">について</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mop op-symbol large-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3717em;vertical-align:-1.3217em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.8557em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⨆</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.3217em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></span></div>
</dd>
</dl>
<p>なお,有限だけ考える場合の連続性だけなら単調性だけから言えて,directed subset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo>=</mo><mo stretchy="false">{</mo><msub><mi>x</mi><mi>i</mi></msub><msub><mo stretchy="false">}</mo><mrow><mn>1</mn><mo>≤</mo><mi>i</mi><mo>≤</mo><mi>n</mi></mrow></msub></mrow><annotation encoding="application/x-tex">P = \{x_i\}_{1 \leq i \leq n}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">}</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span><span class="mrel mtight">≤</span><span class="mord mathnormal mtight">i</span><span class="mrel mtight">≤</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2452em;"><span></span></span></span></span></span></span></span></span></span></span> において, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><mo>⨆</mo><mi>P</mi><mo>∈</mo><mi>P</mi></mrow><annotation encoding="application/x-tex">x = \bigsqcup P \in P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> となるものがあり, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>i</mi><mo separator="true">.</mo><msub><mi>x</mi><mi>i</mi></msub><mo>⊑</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">\forall i\ldotp x_i \sqsubseteq x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord">∀</span><span class="mord mathnormal">i</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> より <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>i</mi><mo separator="true">.</mo><mi>f</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo>⊑</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\forall i\ldotp f(x_i) \sqsubseteq f(x)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∀</span><span class="mord mathnormal">i</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></span> なので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mo>⨆</mo><mi>i</mi></msub><mi>f</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><msub><mo>⨆</mo><mi>i</mi></msub><msub><mi>x</mi><mi>i</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\bigsqcup_i f(x_i) = f(x) = f(\bigsqcup_i x_i)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.162em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.162em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span> となる.なお, pointed cpo に対して連続関数から不動点を作れる (不動点定理).</p>
<dl class="docutils">
<dt>定義. 正格 (strict)</dt>
<dd><p class="first">pointed poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi></mrow><annotation encoding="application/x-tex">E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> への関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi>D</mi><mo>→</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">f: D \to E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> が正格とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi mathvariant="normal">⊥</mi><mo stretchy="false">)</mo><mo>=</mo><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">
f(\bot) = \bot
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord">⊥</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span></div>
</dd>
</dl>
<p>pointed を保存する関数.</p>
<dl class="docutils">
<dt>定義. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-完備半順序 (<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-cpo)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> に対して,</p>
<ul class="simple">
<li>単調関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi>ω</mi><mo>→</mo><mi>D</mi><mo>≃</mo><mo stretchy="false">(</mo><msub><mi>x</mi><mi>n</mi></msub><mo>∈</mo><mi>D</mi><msub><mo stretchy="false">)</mo><mrow><mi>n</mi><mo>∈</mo><mi>ω</mi></mrow></msub></mrow><annotation encoding="application/x-tex">f: \omega \to D \simeq (x_n \in D)_{n \in \omega}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≃</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2274em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span></span></span></span></span> を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-chain と呼ぶ.</li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-chain <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><msub><mi>x</mi><mi>n</mi></msub><msub><mo stretchy="false">)</mo><mrow><mi>n</mi><mo>∈</mo><mi>ω</mi></mrow></msub></mrow><annotation encoding="application/x-tex">(x_n)_{n \in \omega}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2274em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span></span></span></span></span> が sup を持つ時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-cpo と呼ぶ.</li>
</ul>
<p>また, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-cpo <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi></mrow><annotation encoding="application/x-tex">E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> への単調関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi>D</mi><mo>→</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">f: D \to E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-continuous とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mtext>任意の </mtext><mstyle displaystyle="false" scriptlevel="0"><mi>ω</mi></mstyle><mtext>-chain </mtext><mstyle displaystyle="false" scriptlevel="0"><mo stretchy="false">(</mo><msub><mi>x</mi><mi>n</mi></msub><msub><mo stretchy="false">)</mo><mrow><mi>n</mi><mo>∈</mo><mi>ω</mi></mrow></msub></mstyle><mtext> について</mtext></mrow><mtext> </mtext><mi>f</mi><mo stretchy="false">(</mo><munder><mo>⨆</mo><mrow><mi>n</mi><mo>∈</mo><mi>ω</mi></mrow></munder><msub><mi>x</mi><mi>n</mi></msub><mo stretchy="false">)</mo><mo>=</mo><munder><mo>⨆</mo><mrow><mi>n</mi><mo>∈</mo><mi>ω</mi></mrow></munder><mi>f</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>n</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\text{任意の \(\omega\)-chain \((x_n)_{n \in \omega}\) について}\,f(\bigsqcup_{n \in \omega} x_n) = \bigsqcup_{n \in \omega} f(x_n)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:2.3274em;vertical-align:-1.2774em;"></span><span class="mord text"><span class="mord cjk_fallback">任意の</span><span class="mord"> </span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span><span class="mord">-chain </span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2274em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1774em;"><span></span></span></span></span></span></span><span class="mord"> </span><span class="mord cjk_fallback">について</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.9em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⨆</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.2774em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3274em;vertical-align:-1.2774em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.9em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ω</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⨆</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.2774em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></div>
</dd>
</dl>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-chain はつまり可算な増加列のこと.こいつは有限部分集合を取ると明らかに最大要素が一つ確定するため有界であり, directed subset になる.なので, cpo は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-cpo になる.ただ,その逆は成り立たないらしい <a class="footnote-reference" href="#cpo-vs-omega-cpo" id="auto-id-2">[1]</a>. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-cpo でも不動点定理が成り立つ.</p>
<dl class="docutils">
<dt>定理. cpo と連続関数による圏は,CCC</dt>
<dd><p class="first">Cpo を cpo と連続関数から作られる圏とする.この時, Cpo は Cartesian Closed.</p>
<p>証明:</p>
<dl class="last docutils">
<dt>terminal object</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>=</mo><mo stretchy="false">{</mo><mo>∗</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">
1 = \{*\}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">∗</span><span class="mclose">}</span></span></span></span></span></div>
<p class="last">1 要素の cpo への関数は必ず連続になる.</p>
</dd>
<dt>product</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><msub><mi>x</mi><mn>1</mn></msub><mo>⊑</mo><msub><mi>x</mi><mn>2</mn></msub><mo>∈</mo><mi>D</mi><mo separator="true">,</mo><msub><mi>y</mi><mn>1</mn></msub><mo>⊑</mo><msub><mi>y</mi><mn>2</mn></msub><mo>∈</mo><mi>E</mi><mo separator="true">.</mo><mo stretchy="false">(</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>y</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>⊑</mo><mo stretchy="false">(</mo><msub><mi>x</mi><mn>2</mn></msub><mo separator="true">,</mo><msub><mi>y</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>∈</mo><mi>D</mi><mo>×</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">
\forall x_1 \sqsubseteq x_2 \in D, y_1 \sqsubseteq y_2 \in E\ldotp (x_1, y_1) \sqsubseteq (x_2, y_2) \in D \times E
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord">∀</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6891em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span></div>
<p class="last">product order が単純に直積になる.</p>
</dd>
<dt>exponential object</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>D</mi><mi>E</mi></msup><mo>=</mo><mo stretchy="false">{</mo><mi>f</mi><mo>∣</mo><mrow><mtext>連続関数 </mtext><mstyle displaystyle="false" scriptlevel="0"><mi>f</mi><mo>:</mo><mi>D</mi><mo>→</mo><mi>E</mi></mstyle></mrow><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">
D^E = \{f \mid \text{連続関数 \(f: D \to E\)}\}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8913em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">E</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord cjk_fallback">連続関数</span><span class="mord"> </span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span><span class="mclose">}</span></span></span></span></span></div>
<p class="last">pointwise order (<span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>⊑</mo><mi>g</mi><mtext> </mtext><mo>⟺</mo><mtext> </mtext><mi mathvariant="normal">∀</mi><mi>x</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>⊑</mo><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f \sqsubseteq g \iff \forall x \in D\ldotp f(x) \sqsubseteq g(x)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7194em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></span>) 入れた連続関数空間が冪になる.単純に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>a</mi><mi>p</mi><mi>p</mi><mi>l</mi><mi>y</mi></mrow><mo stretchy="false">(</mo><mi>f</mi><mo separator="true">,</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathit{apply}(f, x) = f(x)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">apply</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></span> / <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>c</mi><mi>u</mi><mi>r</mi><mi>r</mi><mi>y</mi></mrow><mo stretchy="false">(</mo><mi>f</mi><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathit{curry}(f)(x)(y) = f(x, y)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">curry</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span> は連続関数になる.</p>
</dd>
</dl>
</dd>
</dl>
</div>
<div class="section" id="auto-id-3">
<h2>ドメイン<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>こっからが本命みたいなとこがある.</p>
<dl class="docutils">
<dt>定義. コンパクト (compact)</dt>
<dd><p class="first">cpo <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> に対して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">x \in D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> がコンパクトとは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mtext>任意の directed subset </mtext><mstyle displaystyle="false" scriptlevel="0"><mi>M</mi><mo>⊆</mo><mi>D</mi></mstyle><mtext> について</mtext></mrow><mtext> </mtext><mi>x</mi><mo>⊑</mo><mo>⨆</mo><mi>M</mi><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mi mathvariant="normal">∃</mi><mi>y</mi><mo>∈</mo><mi>M</mi><mo separator="true">.</mo><mi>x</mi><mo>⊑</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">
\text{任意の directed subset \(M \subseteq D\) について}\,x \sqsubseteq \bigsqcup M \implies \exists y \in M\ldotp x \sqsubseteq y
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord text"><span class="mord cjk_fallback">任意の</span><span class="mord"> directed subset </span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord"> </span><span class="mord cjk_fallback">について</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∃</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></div>
<p class="last">なお, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> の compact elements 全体を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">K</mi><mo stretchy="false">(</mo><mi>D</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\mathrm{K}(D)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm">K</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mclose">)</span></span></span></span></span> と書く.</p>
</dd>
</dl>
<p>cpo の場合のコンパクト性について. compact element は finite element とも呼ばれ,自身を近似するやつ.一般に,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>≪</mo><mi>y</mi><mtext> </mtext><mo>⟺</mo><mtext> </mtext><mo stretchy="false">(</mo><mi mathvariant="normal">∀</mi><mi>M</mi><mo>⊆</mo><mi>D</mi><mo separator="true">.</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mi>M</mi></mstyle><mtext> は directed</mtext></mrow><mo>∧</mo><mi>y</mi><mo>⊑</mo><mo>⨆</mo><mi>M</mi><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mi mathvariant="normal">∃</mi><mi>a</mi><mo>∈</mo><mi>M</mi><mo separator="true">.</mo><mi>x</mi><mo>⊑</mo><mi>a</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
x \ll y \iff (\forall M \subseteq D\ldotp \text{\(M\) は directed} \land y \sqsubseteq \bigsqcup M \implies \exists a \in M\ldotp x \sqsubseteq a)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≪</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7194em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"> </span><span class="mord cjk_fallback">は</span><span class="mord"> directed</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∃</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span></span></span></span></span></div>
<p>を近似関係と言って, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi></mrow><annotation encoding="application/x-tex">y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> を近似すると読む.</p>
<dl class="docutils">
<dt>定義. algebraic</dt>
<dd><p class="first">cpo <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が algebraic とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo>∈</mo><mi>D</mi><mo separator="true">,</mo><mi>M</mi><mo>=</mo><mo stretchy="false">{</mo><mi>a</mi><mo>∈</mo><mi mathvariant="normal">K</mi><mo stretchy="false">(</mo><mi>D</mi><mo stretchy="false">)</mo><mo>∣</mo><mi>a</mi><mo>⊑</mo><mi>x</mi><mo stretchy="false">}</mo><mo separator="true">.</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mi>M</mi></mstyle><mtext> は directed</mtext></mrow><mo>∧</mo><mo>⨆</mo><mi>M</mi><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">
\forall x \in D, M = \{a \in \mathrm{K}(D) \mid a \sqsubseteq x\}\ldotp \text{\(M\) は directed} \land \bigsqcup M = x
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm">K</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">}</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"> </span><span class="mord cjk_fallback">は</span><span class="mord"> directed</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></div>
</dd>
</dl>
<p>algebraic cpo のことを domain と呼ぶことにする. domain 内の要素はそれ以下の compact elements の sup で表せる.これは色々便利な性質だけど,その圏は CCC にならない.具体的には,冪が作れない.</p>
<dl class="docutils">
<dt>定義. 基底 (basis)</dt>
<dd><p class="first">cpo <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> に対して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>D</mi><mn>0</mn></msub><mo>⊆</mo><mi mathvariant="normal">K</mi><mo stretchy="false">(</mo><mi>D</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">D_0 \subseteq \mathrm{K}(D)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm">K</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mclose">)</span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> の基底を成すとは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo>∈</mo><mi>D</mi><mo separator="true">,</mo><mi>M</mi><mo>=</mo><mo stretchy="false">{</mo><mi>a</mi><mo>∈</mo><msub><mi>D</mi><mn>0</mn></msub><mo>∣</mo><mi>a</mi><mo>⊆</mo><mi>x</mi><mo stretchy="false">}</mo><mo separator="true">.</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mi>M</mi></mstyle><mtext> は directed</mtext></mrow><mo>∧</mo><mo>⨆</mo><mi>M</mi><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">
\forall x \in D, M = \{a \in D_0 \mid a \subseteq x\}\ldotp \text{\(M\) は directed} \land \bigsqcup M = x
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">}</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"> </span><span class="mord cjk_fallback">は</span><span class="mord"> directed</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span></div>
</dd>
</dl>
<p>なお, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>D</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">D_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> が <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> の基底を成す時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> は algebraic で <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">K</mi><mo stretchy="false">(</mo><mi>D</mi><mo stretchy="false">)</mo><mo>=</mo><msub><mi>D</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">\mathrm{K}(D) = D_0</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm">K</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> となる. basis を持つ,つまり algebraic の範囲では cpo と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ω</mi></mrow><annotation encoding="application/x-tex">\omega</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">ω</span></span></span></span></span>-cpo は一致するらしい <a class="footnote-reference" href="#cpo-vs-omega-cpo" id="auto-id-4">[1]</a>.</p>
<dl class="docutils">
<dt>定義. 完備束 (complete lattice)</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が完備束とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>M</mi><mo>⊆</mo><mi>D</mi><mo separator="true">.</mo><mo>⨆</mo><mi>M</mi><mo>∈</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">
\forall M \subseteq D\ldotp \bigsqcup M \in D
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span></div>
</dd>
</dl>
<p>なお,この定義は完備半束と呼ばれるやつで,下限でもいい.通常の完備束は,上限下限どちらも要求する.ただ,完備半束は完備束と一致する.つまり,どちらかがあればどちらもある.</p>
<dl class="docutils">
<dt>定理. 完備半束と完備束の一致</dt>
<dd><p class="first">poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> において,以下は同値:</p>
<ol class="arabic simple">
<li>任意の部分集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>⊆</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">M \subseteq D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> は上限を持つ (完備束)</li>
<li>任意の部分集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>⊆</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">M \subseteq D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> は下限を持つ</li>
<li>任意の部分集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>⊆</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">M \subseteq D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> は上限下限を持つ</li>
</ol>
<p>証明:</p>
<p>3 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext></mrow><annotation encoding="application/x-tex">\implies</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.549em;vertical-align:-0.024em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span></span></span></span> 1 / 3 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext></mrow><annotation encoding="application/x-tex">\implies</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.549em;vertical-align:-0.024em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span></span></span></span> 2 / 1 かつ 2 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext></mrow><annotation encoding="application/x-tex">\implies</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.549em;vertical-align:-0.024em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span></span></span></span> 3 はいいので, 1 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext></mrow><annotation encoding="application/x-tex">\implies</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.549em;vertical-align:-0.024em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span></span></span></span> 2 / 2 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext></mrow><annotation encoding="application/x-tex">\implies</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.549em;vertical-align:-0.024em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span></span></span></span> 1 が示せればいい.どちらか片方が示せれば,もう片方は対称的に証明可能なので, 1 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext></mrow><annotation encoding="application/x-tex">\implies</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.549em;vertical-align:-0.024em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span></span></span></span> 2 だけ示す.</p>
<p>まず,空集合を考えるとこいつにも上限があるはずで,そいつは最小元になる.</p>
<p>最小元は,全ての部分集合の下界になるため,少なくとも下界は一つは存在する.任意の部分集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span></span> の下界全体の集合を <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo><mo>↓</mo></mo><mi>M</mi><mo mathvariant="normal">≠</mo><mi mathvariant="normal">∅</mi></mrow><annotation encoding="application/x-tex">\mathop{\downarrow} M \neq \emptyset</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mop" style="position:relative;top:0em;">↓</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em;"></span><span class="mord">∅</span></span></span></span></span> と書くとする.この時, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span></span> の要素は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo><mo>↓</mo></mo><mi>M</mi></mrow><annotation encoding="application/x-tex">\mathop{\downarrow} M</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mop" style="position:relative;top:0em;">↓</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span></span> の上界になり,また <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⨆</mo><mo stretchy="false">(</mo><mo><mo>↓</mo></mo><mi>M</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\bigsqcup (\mathop{\downarrow} M)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mopen">(</span><span class="mop" style="position:relative;top:0em;">↓</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose">)</span></span></span></span></span> が存在するはずで,こいつは以下を満たす:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo fence="true">{</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo>∈</mo><mi>M</mi><mo separator="true">.</mo><mo>⨆</mo><mo stretchy="false">(</mo><mo><mo>↓</mo></mo><mi>M</mi><mo stretchy="false">)</mo><mo>⊑</mo><mi>x</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo>∈</mo><mo><mo>↓</mo></mo><mi>M</mi><mo separator="true">.</mo><mo><mo>↓</mo></mo><mi>M</mi><mo>⊑</mo><mo>⨆</mo><mo stretchy="false">(</mo><mo><mo>↓</mo></mo><mi>M</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow><annotation encoding="application/x-tex">
\left\{\begin{array}{l}
\forall x \in M\ldotp \bigsqcup (\mathop{\downarrow} M) \sqsubseteq x \\
\forall x \in \mathop{\downarrow} M\ldotp \mathop{\downarrow} M \sqsubseteq \bigsqcup (\mathop{\downarrow} M)
\end{array}\right.
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mopen">(</span><span class="mop" style="position:relative;top:0em;">↓</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop" style="position:relative;top:0em;">↓</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop" style="position:relative;top:0em;">↓</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mopen">(</span><span class="mop" style="position:relative;top:0em;">↓</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></div>
<p>つまり, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⨆</mo><mo stretchy="false">(</mo><mo><mo>↓</mo></mo><mi>M</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\bigsqcup (\mathop{\downarrow} M)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mopen">(</span><span class="mop" style="position:relative;top:0em;">↓</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose">)</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span></span> の下界であり,かつ下界の最大要素であるため,下限となる.</p>
<p class="last">以上より,定理が示せる.</p>
</dd>
</dl>
<p>一応束論ってタグつけたので,ちょっとは束論らしいことやらないとね? complete lattice は cpo になる.</p>
<dl class="docutils">
<dt>定義. 有界完備 (bounded complete)</dt>
<dd><p class="first">空でない cpo <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が有界完備とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>任意の有界集合 </mtext><mstyle displaystyle="false" scriptlevel="0"><mi>M</mi><mo>⊆</mo><mi>D</mi></mstyle><mtext> が </mtext><mstyle displaystyle="false" scriptlevel="0"><mo>⨆</mo><mi>M</mi><mo>∈</mo><mi>D</mi></mstyle><mtext> を持つ</mtext></mrow><annotation encoding="application/x-tex">
\text{任意の有界集合 \(M \subseteq D\) が \(\bigsqcup M \in D\) を持つ}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord cjk_fallback">任意の有界集合</span><span class="mord"> </span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord"> </span><span class="mord cjk_fallback">が</span><span class="mord"> </span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord"> </span><span class="mord cjk_fallback">を持つ</span></span></span></span></span></span></div>
</dd>
</dl>
<p>なお, cpo は directed complete な poset と呼ばれることがあり, directed + bounded complete な poset が, bounded complete cpo になる.bounded complete な domain を, bc-domain と呼ぶことにする. bc-domain による圏は CCC になる.</p>
<dl class="docutils">
<dt>補題. 点付き有界完備 cpo の同値条件</dt>
<dd><p class="first">pointed cpo <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> において,以下は同値:</p>
<ol class="arabic simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> は bounded complete</li>
<li>任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>↑</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \uparrow y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊔</mo><mi>y</mi><mo>∈</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">x \sqcup y \in D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span></li>
</ol>
<p>証明:</p>
<p>1 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext></mrow><annotation encoding="application/x-tex">\implies</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.549em;vertical-align:-0.024em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span></span></span></span> 2 は,有界集合として <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>=</mo><mo stretchy="false">{</mo><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">M = \{x, y\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">}</span></span></span></span></span> を取れば自明に成り立つ.</p>
<p>2 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext> </mtext><mo>⟹</mo><mtext> </mtext></mrow><annotation encoding="application/x-tex">\implies</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.549em;vertical-align:-0.024em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span></span></span></span> 1 は,以下のように示せる <a class="footnote-reference" href="#helped-proof" id="auto-id-5">[2]</a>.</p>
<p>任意の有界部分集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi><mo>⊆</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">M \subseteq D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>M</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∈</mo><msub><mi mathvariant="script">P</mi><mrow><mi>f</mi><mi>i</mi><mi>n</mi></mrow></msub><mo stretchy="false">(</mo><mi>M</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">M' \in \mathcal{P}_{\mathit{fin}}(M)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.791em;vertical-align:-0.0391em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0822em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathit mtight">fin</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose">)</span></span></span></span></span> は有界で有限なので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">⊥</mi></mrow><annotation encoding="application/x-tex">\bot</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">⊥</span></span></span></span></span> から各要素の sup 取りまくれば全体の sup が作れる.</p>
<p>ここで, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi><mo>=</mo><mo stretchy="false">{</mo><mo>⨆</mo><msup><mi>M</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∣</mo><msup><mi>M</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∈</mo><msub><mi mathvariant="script">P</mi><mrow><mi>f</mi><mi>i</mi><mi>n</mi></mrow></msub><mo stretchy="false">(</mo><mi>M</mi><mo stretchy="false">)</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">N = \{\bigsqcup M' \mid M' \in \mathcal{P}_{\mathit{fin}}(M)\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0019em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.791em;vertical-align:-0.0391em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0822em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathit mtight">fin</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose">)}</span></span></span></span></span> を考える.こいつは,任意の <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>U</mi><mo>∈</mo><msub><mi mathvariant="script">P</mi><mrow><mi>f</mi><mi>i</mi><mi>n</mi></mrow></msub><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">U \in \mathcal{P}_{\mathit{fin}}(N)</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0822em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathit mtight">fin</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span></span> に対して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⨆</mo><mo>⋃</mo><mo stretchy="false">{</mo><msup><mi>M</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∣</mo><mo>⨆</mo><msup><mi>M</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>∈</mo><mi>U</mi><mo stretchy="false">}</mo><mo>∈</mo><mi>U</mi></mrow><annotation encoding="application/x-tex">\bigsqcup \bigcup \{M' \mid \bigsqcup M' \in U\} \in U</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.0019em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆⋃</span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0019em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span></span></span></span></span> が上界となるので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>U</mi></mrow><annotation encoding="application/x-tex">U</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span></span></span></span></span> は directed set になる. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> は cpo なので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⨆</mo><mi>U</mi><mo>∈</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">\bigsqcup U \in D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が存在する.</p>
<p class="last"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⨆</mo><mi>U</mi></mrow><annotation encoding="application/x-tex">\bigsqcup U</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span></span> の上界であり,他の任意の上界は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>U</mi></mrow><annotation encoding="application/x-tex">U</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span></span></span></span></span> の上界にもなるので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⨆</mo><mi>M</mi><mo>=</mo><mo>⨆</mo><mi>U</mi></mrow><annotation encoding="application/x-tex">\bigsqcup M = \bigsqcup U</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨆</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span></span></span></span></span> となる.よって,題意は成り立つ.</p>
</dd>
</dl>
<p>2 の逆は sup があれば有界なことより自明なので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>↑</mo><mi>y</mi></mrow><annotation encoding="application/x-tex">x \mathrel{\uparrow} y</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">↑</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span> と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊔</mo><mi>y</mi><mo>∈</mo><mi>D</mi></mrow><annotation encoding="application/x-tex">x \sqcup y \in D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> は bc-domain では同値条件になる.</p>
<dl class="docutils">
<dt>定義. 単項イデアル (principal ideal)</dt>
<dd>poset <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> , <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>∈</mo><mi>P</mi></mrow><annotation encoding="application/x-tex">x \in P</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></span> について, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></span> により生成される単項イデアルとは,集合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>↓</mo><mi>x</mi><mo>=</mo><mo stretchy="false">{</mo><mi>y</mi><mo>∈</mo><mi>P</mi><mo>∣</mo><mi>y</mi><mo>⊑</mo><mi>x</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\downarrow x = \{y \in P \mid y \sqsubseteq x\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mrel">↓</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">}</span></span></span></span></span> のこと.</dd>
<dt>定義. property I</dt>
<dd><p class="first">algebraic cpo <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が property I を持つとは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>a</mi><mo>∈</mo><mi mathvariant="normal">K</mi><mo stretchy="false">(</mo><mi>D</mi><mo stretchy="false">)</mo><mo separator="true">.</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mo>↓</mo><mi>a</mi></mstyle><mtext> は有限</mtext></mrow></mrow><annotation encoding="application/x-tex">
\forall a \in \mathrm{K}(D)\ldotp \text{\(\downarrow a\) は有限}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathrm">K</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mclose">)</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mrel">↓</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">a</span><span class="mord"> </span><span class="mord cjk_fallback">は有限</span></span></span></span></span></span></div>
</dd>
</dl>
<p>property I + bounded complete な domain では,有限個で要素を近似できる.ただ, CCC は作れない.これはやっぱり冪が作れないから.単なる連続関数空間が property I を持たないため.</p>
<dl class="docutils">
<dt>定義. 分配的 (distributive)</dt>
<dd><p class="first">bc-domain <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> が分配的とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>↑</mo><mi>z</mi><mo>∈</mo><mi>D</mi><mo separator="true">.</mo><mi>x</mi><mo>⊓</mo><mo stretchy="false">(</mo><mi>y</mi><mo>⊔</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>⊓</mo><mi>y</mi><mo stretchy="false">)</mo><mo>⊔</mo><mo stretchy="false">(</mo><mi>x</mi><mo>⊓</mo><mi>z</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\forall x, y \uparrow z \in D\ldotp x \sqcap (y \sqcup z) = (x \sqcap y) \sqcup (x \sqcap z)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊔</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></div>
</dd>
</dl>
<p>distributive で property I を持つ bc-domain を dI-domain と呼ぶことにする.</p>
<dl class="docutils">
<dt>定義. stable</dt>
<dd><p class="first">dI-domain <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>D</mi></mrow><annotation encoding="application/x-tex">D</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span> から <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi></mrow><annotation encoding="application/x-tex">E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> への連続関数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo>:</mo><mi>D</mi><mo>→</mo><mi>E</mi></mrow><annotation encoding="application/x-tex">f: D \to E</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span></span></span></span></span> が, stable とは,以下を満たすこと:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>x</mi><mo>↑</mo><mi>y</mi><mo separator="true">.</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo>⊓</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>⊓</mo><mi>f</mi><mo stretchy="false">(</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\forall x \uparrow y\ldotp f(x \sqcap y) = f(x) \sqcap f(y)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></div>
</dd>
</dl>
<p>dI-domain と stable function による圏は CCC になる.冪は,以下の stable order で作る:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><msub><mo>⊑</mo><mi>s</mi></msub><mi>g</mi><mtext> </mtext><mo>⟺</mo><mtext> </mtext><mi mathvariant="normal">∀</mi><mi>x</mi><mo>⊑</mo><mi>y</mi><mo separator="true">.</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><mi>y</mi><mo stretchy="false">)</mo><mo>⊓</mo><mi>g</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
f \sqsubseteq_s g \iff \forall x \sqsubseteq y\ldotp f(x) = f(y) \sqcap g(x)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">⊑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7194em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></span></div>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>色々数式環境お試しのために書いた. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>KaTeX</mtext></mrow><annotation encoding="application/x-tex">\KaTeX</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8988em;vertical-align:-0.2155em;"></span><span class="mord text"><span class="mord textrm">K</span><span class="mspace" style="margin-right:-0.17em;"></span><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6833em;"><span style="top:-2.905em;"><span class="pstrut" style="height:2.7em;"></span><span class="mord"><span class="mord textrm mtight sizing reset-size6 size3">A</span></span></span></span></span></span><span class="mspace" style="margin-right:-0.15em;"></span><span class="mord text"><span class="mord textrm">T</span><span class="mspace" style="margin-right:-0.1667em;"></span><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4678em;"><span style="top:-2.7845em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord textrm">E</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2155em;"><span></span></span></span></span><span class="mspace" style="margin-right:-0.125em;"></span><span class="mord textrm">X</span></span></span></span></span></span></span> では, <tt class="docutils literal">\bigsqcap</tt> が書けないこととかが分かった.</p>
<p>これで,某勉強会のコーヒーブレイクタイムが終わっても,元の話題をちゃんと思い出せるといいな.</p>
<table class="docutils footnote" frame="void" id="cpo-vs-omega-cpo" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label">[1]</td><td><em>(<a class="fn-backref" href="#auto-id-2">1</a>, <a class="fn-backref" href="#auto-id-4">2</a>)</em> <a class="reference external" href="https://en.wikipedia.org/wiki/Complete_partial_order#Definitions">https://en.wikipedia.org/wiki/Complete_partial_order#Definitions</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="helped-proof" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[2]</a></td><td>これ自力じゃ証明できなくて,某勉強会の人に教えてもらった.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/05/cpo-related-definitions.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/05/cpo-related-definitions.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>KaTeX コードを静的にレンダリングする2019-04-28T07:10:54+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-28:/blog/posts/2019/04/to-use-serverside-katex/<p>ふと, KaTeX ってサーバサイドレンダリングできないかと思って試してみたら,普通に楽にできそうだったので,ブログで …</p><p>ふと, KaTeX ってサーバサイドレンダリングできないかと思って試してみたら,普通に楽にできそうだったので,ブログでやってみることにした.</p>
<div class="section" id="auto-id-1">
<h2>KaTeX をサーバサイドレンダリングする<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>特に難しいことはなくて, KaTeX は Node.js 上で動くっぽく,以下のようにすれば HTML を生成できるっぽい:</p>
<pre class="literal-block">
$ node --eval 'const KaTeX = require("katex"); console.log(KaTeX.renderToString("x"));'
<span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault">x</span></span></span></span>
</pre>
<p>これを利用して, Pelican のプラグインから Node.js で KaTeX のレンダリングを行うようにする.まず, JavaScript のコードで,次のようなものを書いた:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span></pre></div></td><td class="code"><div><pre><span></span><span class="ch">#!/usr/bin/env node</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">KaTeX</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">require</span><span class="p">(</span><span class="s2">"katex"</span><span class="p">);</span>
<span class="kd">function</span><span class="w"> </span><span class="nx">katexRenderingPipe</span><span class="p">(</span><span class="nx">instream</span><span class="p">,</span><span class="w"> </span><span class="nx">outstream</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">chunkrest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">;</span>
<span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">onData</span><span class="p">(</span><span class="nx">chunk</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">chunks</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">chunk</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="s2">"utf8"</span><span class="p">).</span><span class="nx">split</span><span class="p">(</span><span class="s2">"\t\n"</span><span class="p">);</span>
<span class="w"> </span><span class="nx">chunks</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">chunkrest</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">chunks</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span>
<span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">l</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">chunks</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o"><</span><span class="w"> </span><span class="nx">l</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">str</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">chunks</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\t /g</span><span class="p">,</span><span class="w"> </span><span class="s2">"\t"</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="ow">typeof</span><span class="w"> </span><span class="nx">str</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"string"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"not string stream"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">outstream</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">KaTeX</span><span class="p">.</span><span class="nx">renderToString</span><span class="p">(</span><span class="nx">str</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\t/g</span><span class="p">,</span><span class="w"> </span><span class="s2">"\t "</span><span class="p">));</span>
<span class="w"> </span><span class="nx">outstream</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="s2">"\t\n"</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">chunkrest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">chunks</span><span class="p">[</span><span class="nx">l</span><span class="p">];</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="nx">instream</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s2">"data"</span><span class="p">,</span><span class="w"> </span><span class="nx">onData</span><span class="p">);</span>
<span class="w"> </span><span class="nx">instream</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s2">"end"</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">outstream</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="s1">''</span><span class="p">);</span>
<span class="w"> </span><span class="p">});</span>
<span class="p">}</span>
<span class="nx">katexRenderingPipe</span><span class="p">(</span><span class="nx">process</span><span class="p">.</span><span class="nx">stdin</span><span class="p">,</span><span class="w"> </span><span class="nx">process</span><span class="p">.</span><span class="nx">stdout</span><span class="p">);</span>
</pre></div></td></tr></table></div>
<p>このプログラムは,区切り文字で区切って送られてくる数式文字列を受け取って,それを <tt class="docutils literal">KaTeX</tt> に渡し,レンダリングされた文字列を返すプログラムになる.データのシリアライズ形式としてめっちゃ単純なものを使っていて,ほぼ文字列そのままでタブ文字はその後に空白を入れる.後はその文字列をタブ文字改行で区切って送るだけ.送った先ではタブ文字空白をタブ文字に変換する.こうすると,区切り文字が一定に決まる. HTTP でも過去には一部のブラウザで似たようなことが行われていた気がする.タブ文字は,送る数式にも返ってくる HTML にも入ってないであろうと想定して,デバッグの時に視覚的に見分けられる文字として選んでる.後は, Pelican 側から,上のスクリプトを立ち上げて随時数式文字列を送り,返ってきた HTML で数式環境を置き換えるだけ.ただそれだけなんだが, Python 初心者なので色々手こずった.なので,以降主に Python についての内容になる.</p>
</div>
<div class="section" id="asyncio">
<h2>asyncio を使う<a class="headerlink" href="#asyncio" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Node.js に合わせて Python も非同期 I/O を使おうと思って, Python 標準の <tt class="docutils literal">asyncio</tt> モジュールを使ってみることにした. Python には, 3.5 から async/await 構文が入っている.感覚的には, JavaScript の async/await と変わらなくて,</p>
<pre class="literal-block">
async def f(x):
return await g(x)
</pre>
<p>は,以下のと大体同じ:</p>
<pre class="literal-block">
import asyncio
@asyncio.coroutine
def f(x):
return yield from g(x)
</pre>
<p><tt class="docutils literal">@asyncio.coroutine</tt> デコレータは将来消されるらしいけど <a class="footnote-reference" href="#asyncio-coroutine-decolator-deprecated" id="auto-id-2">[1]</a>,イメージ的にはジェネレータの各ステップを適宜 Future に包むながら繋げていく感じ.で,そのデコレータを使わないで,同様のことを簡単に書けるのが async / await 構文で,デコレータに包まれたジェネレータの定義が <tt class="docutils literal">async def</tt> , <tt class="docutils literal">yield from</tt> が <tt class="docutils literal">await</tt> な感じ.まあ,実は僕もそこまで深く理解してないんだけど.</p>
<p>Node.js との違いは,イベントループに対する明示的な操作がかなりできることっぽい.イベントループ止めたりもできる.この辺よく分かってないけど,とりあえず</p>
<pre class="literal-block">
asyncio.run(f("arg"))
</pre>
<p>とかしとけば,</p>
<ol class="arabic simple">
<li>イベントループをカレントスレッドに作成する (既にあればエラーになる) .</li>
<li>返ってきたコルーチンオブジェクトを,作成したイベントループで処理する.</li>
<li>処理し終えたら,イベントループを破棄して,結果に応じて値または例外を出す.</li>
</ol>
<p>みたいなことをしてくれるっぽい.他にも色々 API があるんだけど,フォークに対応してなかったり <a class="footnote-reference" href="#fork-asyncio-issue" id="auto-id-3">[2]</a>,微妙に使い方分からなかったり.なので,適当に <tt class="docutils literal">run</tt> 使うことにした.</p>
<p><tt class="docutils literal">asyncio</tt> モジュールでは,この async/await に対応した非同期 I/O API も提供している.今回は, Node.js のスクリプトを立ち上げるため,サブプロセス関係の API を使う. <tt class="docutils literal">asyncio</tt> モジュールのサブプロセス関係の API は,基本的に <tt class="docutils literal">subprocess</tt> モジュールと扱い方は変わらなくって,コルーチンオブジェクトを返すようになってるだけ.以下のように使う:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span></pre></div></td><td class="code"><div><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">asyncio</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">ls1</span><span class="p">():</span>
<span class="n">proc</span> <span class="o">=</span> <span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">create_subprocess_exec</span><span class="p">(</span>
<span class="s2">"ls"</span><span class="p">,</span>
<span class="s2">"-1"</span><span class="p">,</span>
<span class="n">stdin</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">stdout</span><span class="o">=</span><span class="n">asyncio</span><span class="o">.</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="k">await</span> <span class="n">proc</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">readline</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">buffer</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="k">await</span> <span class="n">proc</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">ls1</span><span class="p">())</span>
</pre></div></td></tr></table></div>
<p>ところで,対象が <tt class="docutils literal">ls</tt> コマンドならいいんだけど,今呼び出したいプログラムは EOF を送らないと終了しないようになっているので,呼び出し側で例外が発生すると,そのままプロセスが閉じないで色々あれなことになる.なので,プロセスのリソース管理をして,例外が発生したら呼び出してるプロセスに <tt class="docutils literal">SIGTERM</tt> を送るようにしたい.これには, with 構文の async 版, async with が使える. async with は <tt class="docutils literal">__aenter__</tt> / <tt class="docutils literal">__aexit__</tt> というプロトコルメソッドを使う.サブプロセスの管理は,以下のように書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span>
<span class="normal">32</span>
<span class="normal">33</span>
<span class="normal">34</span>
<span class="normal">35</span>
<span class="normal">36</span>
<span class="normal">37</span>
<span class="normal">38</span>
<span class="normal">39</span>
<span class="normal">40</span>
<span class="normal">41</span>
<span class="normal">42</span>
<span class="normal">43</span>
<span class="normal">44</span>
<span class="normal">45</span></pre></div></td><td class="code"><div><pre><span></span><span class="n">STREAM_CHUNK_LIMIT</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">**</span> <span class="mi">16</span>
<span class="k">class</span> <span class="nc">KaTeXRendererManager</span><span class="p">:</span>
<span class="k">async</span> <span class="k">def</span> <span class="fm">__aenter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">proc</span> <span class="o">=</span> <span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">create_subprocess_exec</span><span class="p">(</span>
<span class="s1">'node'</span><span class="p">,</span>
<span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)),</span> <span class="s1">'katex_render.js'</span><span class="p">),</span>
<span class="n">stdin</span><span class="o">=</span><span class="n">asyncio</span><span class="o">.</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">,</span>
<span class="n">stdout</span><span class="o">=</span><span class="n">asyncio</span><span class="o">.</span><span class="n">subprocess</span><span class="o">.</span><span class="n">PIPE</span><span class="p">,</span>
<span class="n">limit</span><span class="o">=</span><span class="n">STREAM_CHUNK_LIMIT</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">proc</span>
<span class="k">async</span> <span class="k">def</span> <span class="fm">__aexit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc</span><span class="p">,</span> <span class="n">tb</span><span class="p">):</span>
<span class="k">if</span> <span class="n">exc</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">terminate</span><span class="p">()</span>
<span class="k">return</span>
<span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">proc</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">render_math_contents</span><span class="p">(</span><span class="n">contents</span><span class="p">):</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">KaTeXRendererManager</span><span class="p">()</span> <span class="k">as</span> <span class="n">proc</span><span class="p">:</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">readuntil_sep</span><span class="p">():</span>
<span class="n">chunk</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">''</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">chunk</span> <span class="o">=</span> <span class="n">chunk</span> <span class="o">+</span> <span class="k">await</span> <span class="n">proc</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">readuntil</span><span class="p">(</span><span class="sa">b</span><span class="s1">'</span><span class="se">\t\n</span><span class="s1">'</span><span class="p">)</span>
<span class="k">except</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">LimitOverrunError</span><span class="p">:</span>
<span class="n">chunk</span> <span class="o">=</span> <span class="n">chunk</span> <span class="o">+</span> <span class="k">await</span> <span class="n">proc</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">STREAM_CHUNK_LIMIT</span> <span class="o">-</span> <span class="mi">1024</span><span class="p">)</span>
<span class="k">continue</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">break</span>
<span class="k">return</span> <span class="n">chunk</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="sa">b</span><span class="s1">'</span><span class="se">\t</span><span class="s1"> '</span><span class="p">,</span> <span class="sa">b</span><span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">content</span> <span class="ow">in</span> <span class="n">contents</span><span class="p">:</span>
<span class="n">proc</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">content</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="sa">b</span><span class="s1">'</span><span class="se">\t</span><span class="s1">'</span><span class="p">,</span> <span class="sa">b</span><span class="s1">'</span><span class="se">\t</span><span class="s1"> '</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">())</span>
<span class="n">proc</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="sa">b</span><span class="s1">'</span><span class="se">\t\n</span><span class="s1">'</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="k">await</span> <span class="n">readuntil_sep</span><span class="p">())</span>
<span class="n">proc</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write_eof</span><span class="p">()</span>
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">render_math_contents</span><span class="p">([</span><span class="s1">'f(x) = 2^x'</span><span class="p">,</span> <span class="s1">'n </span><span class="se">\\</span><span class="s1">in </span><span class="se">\\</span><span class="s1">mathbb</span><span class="si">{N}</span><span class="s1">'</span><span class="p">]))</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">async with</tt> が呼ばれた時に, <tt class="docutils literal">__aenter__</tt> で返されたものが束縛され,処理が終了するか例外が出ると <tt class="docutils literal">__aexit__</tt> が呼ばれる.なお, <tt class="docutils literal">__aexit__</tt> は,正常終了すると引数に <tt class="docutils literal">None</tt> が入れられて呼ばれる.なお,サブプロセスから読み取るチャンクの最大サイズはデフォルトで, 64KB (= <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mn>16</mn></msup></mrow><annotation encoding="application/x-tex">2 ^ {16}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">16</span></span></span></span></span></span></span></span></span></span></span></span></span> B) が指定されてる.これを超えるものを読み取ろうとすると, <tt class="docutils literal">LimitOverrunError</tt> 例外が発生する:</p>
<pre class="literal-block">
ValueError: Separator is not found, and chunk exceed the limit
</pre>
<p>これを解決するため,例外が発生するとまずちょっと読み取って,それから再度挑戦するみたいなことをしてる.ここまでくれば,後は適当に BeautifulSoup を使って数式 DOM 部分を置換していくプラグインを書くだけだった.</p>
</div>
<div class="section" id="python">
<h2>Python のデバッグをする<a class="headerlink" href="#python" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>プラグインを書く際,結構色々バグってデバッグをたくさんした.特に, Pelican だとエラーはメッセージしか表示されなくて,トレースバックが表示されなくて,色々難航したので,トレースバックを表示する方法を色々調べた.結論としては,以下のようにすればトレースバックを表示できるっぽい:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kn">import</span> <span class="nn">traceback</span>
<span class="k">try</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">traceback</span><span class="o">.</span><span class="n">format_exception</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">__traceback__</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="n">line</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span>
<span class="k">raise</span> <span class="n">e</span>
</pre></div></td></tr></table></div>
<p>Python 3.5 から <tt class="docutils literal">traceback.format_exception</tt> の一番目の引数は勝手に検知してくれるようになったので,特に指定しなくて大丈夫みたい.推測してくれない場合,エラーの型を書く必要がある.後,プロファイルが取りたければ次のようにする:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div><pre><span></span><span class="kn">import</span> <span class="nn">pstats</span>
<span class="kn">import</span> <span class="nn">cProfile</span>
<span class="n">pr</span> <span class="o">=</span> <span class="n">cProfile</span><span class="o">.</span><span class="n">Profile</span><span class="p">()</span>
<span class="n">pr</span><span class="o">.</span><span class="n">enable</span><span class="p">()</span>
<span class="o">...</span>
<span class="n">pr</span><span class="o">.</span><span class="n">disable</span><span class="p">()</span>
<span class="sd">"""</span>
<span class="sd">ファイル出力の場合:</span>
<span class="sd">pstats.Stats(pr).dump_stats('profile.stats')</span>
<span class="sd">pstats.Stats('profile.stats')</span>
<span class="sd">"""</span>
<span class="c1"># 累計時間でソートして,上位 10 件表示</span>
<span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="n">pr</span><span class="p">)</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="n">pstats</span><span class="o">.</span><span class="n">SortKey</span><span class="o">.</span><span class="n">CUMULATIVE</span><span class="p">)</span><span class="o">.</span><span class="n">print_stats</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>なんかまあ,そんな感じ.</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>サーバサイドレンダリングで, JavaScript をブラウザで動かさずに数式を見れるようにした.でも,結構ビルドが遅くなっちゃった.</p>
<p>なんか色々調整してみたけど,大体文書 18 個,ページ 3 個で 8 秒ぐらいかかる. KaTeX のビルドをしなければ 3 秒ぐらいで済む.これ何とかしたいんだけど, KaTeX は Node.js 上でしか動かないし, Pelican は Python が必要だし,プラグインの制約も色々あるし,うーんという感じ.多分サブプロセスの立ち上げと, Node.js と Python 間の通信が一番コストになってる.通信は gzip 圧縮でもしてみようかと思ったけど,めんどいのでやめた.まあ,色々対策を考えてみるかという感じ.</p>
<table class="docutils footnote" frame="void" id="asyncio-coroutine-decolator-deprecated" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><a class="reference external" href="https://docs.python.org/ja/3.7/library/asyncio-task.html#asyncio.coroutine">https://docs.python.org/ja/3.7/library/asyncio-task.html#asyncio.coroutine</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="fork-asyncio-issue" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[2]</a></td><td><a class="reference external" href="https://bugs.python.org/issue21998">https://bugs.python.org/issue21998</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/to-use-serverside-katex.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/to-use-serverside-katex.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>OSS ライセンスについての色々2019-04-25T09:58:21+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-25:/blog/posts/2019/04/about-oss-licenses/<p>Haskell-jp でちょっと話題になったので, OSS ライセンスについての個人的な色々を書いておこうと思う.なお,僕は OSS にも著作権にも明るくないので …</p><p>Haskell-jp でちょっと話題になったので, OSS ライセンスについての個人的な色々を書いておこうと思う.なお,僕は OSS にも著作権にも明るくないので,この記事は多数間違いを含む可能性がある.それぞれ僕の独自の解釈の可能性があるので,そこは注意してほしい.</p>
<div class="section" id="auto-id-1">
<h2>OSS ライセンスについて<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>そもそもライセンスとは,要は許可証で,何かを使用する際に,その配布者がそれを使って何をして良いか何をしてはいけないかを書いた文書のことだ.配布者が「それを守れるなら使っていいよ」と,使用許諾を出すときに出す契約書のようなものだ.</p>
<p>OSS ライセンスは,その文書のテンプレのようなもので,現在は <a class="reference external" href="https://opensource.org/">Open Source Initiative</a> ,通称 OSI が承認したものを指す事が多いんじゃないだろうか.そのリストは <a class="reference external" href="https://opensource.org/licenses/alphabetical">https://opensource.org/licenses/alphabetical</a> から見れる.有名な <a class="reference external" href="https://opensource.org/osd">オープンソースの定義</a> ( <a class="reference external" href="https://opensource.org/osd-annotated">注記付き版</a> ) で決められた制約を満たしているか精査されたものが,承認される.大雑把に言えば,</p>
<ul class="simple">
<li>再頒布を制限しない.再頒布に対して報酬や制約を要求しない.</li>
<li>ソースコードの頒布を制限してはいけない.</li>
<li>同じライセンスで追加コードを一緒に頒布するのを妨げてはいけない.</li>
<li>特定の個人やグループを差別して,あるグループだけに特別な制約をかけてはいけない.</li>
</ul>
<p>という感じだ.僕が観測しているよく使われている OSS ライセンスは,以下のもの:</p>
<dl class="docutils">
<dt>GNU General Public License Version 3.0</dt>
<dd><p class="first">通称 GPL .コピーレフトと呼ばれる特徴を持つ <a class="footnote-reference" href="#copyleft-is-minor" id="auto-id-4">[1]</a>.古くは, GPL Version 2.0 がよく使われていたのだが,そのままじゃ色々古いよねという事で作られた.コピーレフトは後ほど説明するが,この特徴はライブラリを組み合わせるとき非常に都合が悪い.なので,使用者に不自由を強いたくないなら,他のライセンスを使うことをお勧めする.</p>
<p>なお,歴史的事情により多くの主要なプログラムは GPL Version 2.0 を使っている.この辺も後ほど説明する.</p>
<p>採用してるソフトウェアは, Ansible / GCC / Moodle など</p>
<p class="last"><a class="reference external" href="https://opensource.org/licenses/GPL-3.0">https://opensource.org/licenses/GPL-3.0</a> (公式: <a class="reference external" href="https://www.gnu.org/licenses/gpl-3.0.en.html">https://www.gnu.org/licenses/gpl-3.0.en.html</a>)</p>
</dd>
<dt>The 3-Clause BSD License</dt>
<dd><p class="first">通称「修正BSDライセンス」. BSD ライセンスの 3 条項目,いわゆる宣伝条項が GPL と両立しないため,当時その条項が消されたものを使う事が多々あった.これをとりまとめたライセンス.条文がかなり少ない上,制約もかなり緩い. GPL のコピーレフトに対抗して作られたようなもので,現在よく使われてるライセンスの多くは,このライセンスの流れを汲んでいる.</p>
<p>採用してるソフトウェアは, Golang / d3.js / Redis / googletest など</p>
<p class="last"><a class="reference external" href="https://opensource.org/licenses/BSD-3-Clause">https://opensource.org/licenses/BSD-3-Clause</a></p>
</dd>
<dt>Apache License, Version 2.0</dt>
<dd><p class="first">割と新しいライセンスで, BSD 系の緩すぎる制約を少し見直し,制約を明確化し特許保護の規定を盛り込んだライセンス. GPL を忌避する界隈ではよく使われてる気がする.</p>
<p>採用してるソフトウェアは, Kubernetes / OpenSSL (v3 以降) / TypeScript / Apache Solr など</p>
<p class="last"><a class="reference external" href="https://opensource.org/licenses/Apache-2.0">https://opensource.org/licenses/Apache-2.0</a> (公式: <a class="reference external" href="https://www.apache.org/licenses/LICENSE-2.0">https://www.apache.org/licenses/LICENSE-2.0</a>)</p>
</dd>
<dt>MIT License (Expat License, X11 License)</dt>
<dd><p class="first">ライセンス条項がかなり短いやつ.ほとんど何も制限していない, GPL の当て付けみたいなライセンス. BSD ライセンスの癖のある条項消したら,こうなったみたいな感じ.割とちゃんとライセンスを考えるならオススメしないが, GPL や他のライセンスとの兼ね合いからこのライセンスにせざるを得ないみたいな場合もある.ただ NPM 界隈は,結構脳死でこのライセンスにしてるソフトが多い気がする (付属ライブラリが多い傾向にあるからかな) .</p>
<p>採用してるソフトウェアは, Angular.js / VSCode / Twitter Bootstrap など</p>
<p class="last"><a class="reference external" href="https://opensource.org/licenses/MIT">https://opensource.org/licenses/MIT</a></p>
</dd>
<dt>Mozilla Public License Version 2.0</dt>
<dd><p class="first">通称 MPL .GPL との両立を見据えた特殊なライセンス.他のライセンスとの運用でも, MPL の部分だけは保護するようなライセンスとなる.運用が少し難しいが,新しいライセンスで,制約を明確化し特許保護の規定が盛り込まれているので,コピーレフトな運用がしたいならいいと思う.</p>
<p>採用してるソフトウェアは, Consul / Boulder (ACME CA) / Mozilla Firefox など</p>
<p class="last"><a class="reference external" href="https://opensource.org/licenses/MPL-2.0">https://opensource.org/licenses/MPL-2.0</a> (公式: <a class="reference external" href="https://www.mozilla.org/en-US/MPL/2.0/">https://www.mozilla.org/en-US/MPL/2.0/</a>)</p>
</dd>
</dl>
<p>他にも著名なのはいくらでもあるけどね.</p>
</div>
<div class="section" id="gpl">
<h2>GPL 汚染<a class="headerlink" href="#gpl" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて, OSS ライセンスの話でよくコピーレフトと非コピーレフトという話が出てくるが,実際問題としてコピーレフトという機能を積んでるのは GPL 系 (GNU Public License 系と MPL) だけだ.そして,最近 GPL はあまり選ばれなくなってきてる.なんで選ばれなくなってきてるかというと,単純に知名度の問題と,皮肉にもその特徴であるコピーレフトの起因がある.ただ,選ばれなくなってきてるとはいえ,ここら辺話さざるを得ない話題なので,まずはここから話していく.</p>
<p>そもそも,一昔前までは GPL というのは OSS ライセンスの代名詞みたいな存在だった.で,多くの主要なプロジェクトはこのライセンスを使っていた.特に, GPL 2.0 は数多くのプロジェクトで使われたわけだけど,このライセンス,かなり癖が強かった.その癖の 1 つが GPL の代名詞と言えるコピーレフトだ.コピーレフトの要点は 2 つだ:</p>
<ul class="simple">
<li>再頒布は同じライセンスで行わなければならない.</li>
<li>再頒布の際,追加の制限をかけてはならない.</li>
</ul>
<p>MPL もこの条項を持っているが, GPL はその適用範囲が賛否両論を生んでいる.それは「結合された作品 (Conveying Works)」の再頒布の際も上の制約がかかることだ.つまり,例えば GPL で提供されるライブラリ A をライブラリ B が使う場合, B をコンパイルしてそのライブラリアーカイブを頒布する際は GPL 下で頒布しなければいけないし,ライブラリ B をプログラム C が使う場合やはり実行ファイルは GPL 下で頒布しなければいけないということだ. MPL はその範囲を頒布者が明示的に制限することになっていて,その範囲を超える場所は特に制限はないけど,明示的に制限された場所に関しては MPL の条項に従う必要がある.</p>
<p>再頒布の際追加の制限をかけてはいけないというのは,例えばある頒布元で秘密保持契約を結ばされて秘密裏に頒布されるみたいなことを防ぐためだけど,おかげで GPL 2.0 で配布されたものに追加の制限がかけられず,他のライセンスのプログラムと組み合わせられないみたいなことも多数起きた. GPL 3.0 のプログラムさえ, GPL 2.0 と組み合わせられない.</p>
<p>よって, GPL 下のライブラリに依存してしまうと,そのライブラリを含むライブラリも GPL で頒布になり,そのライブラリを含むプログラムもやはり GPL で頒布になり, GPL は追加制限をかけられないので GPL より制限の強いライセンスでは頒布できない <a class="footnote-reference" href="#image-copyleft" id="auto-id-5">[2]</a> ので, GPL の範囲がじわじわ広がっていってそれを止められもしないということになる.これは, GPL を作った人たちにとって狙い通りなわけだけど, GPL とは無縁でいたい人たちからはたまったものではなく,「コピーレフト汚染」もしくは「GPL 汚染」と呼ばれたりする.</p>
<p>後, GPL や MPL では著作権保有者という概念はなく,あるのはこのプログラムは GPL でライセンスされてるという契約だけで,権利を作成者も再頒布者も主張できない.特に, GPL 3.0 では特許についての明確な条項が入ったので,何か権利も主張できないしコードも公開しなければいけない,そんな何かがじわじわ広がっていくことになる.</p>
<p>ただ,注意して欲しいのは, GPL ライセンスが適用される範囲はあくまで結合全体であり, GPL と組み合わせる前提のプログラムを同じライセンスで頒布しなければならないというわけではないということだ.ここでの結合とは,静的 / 動的リンクなどを行ったものを指す.実際にプログラムを頒布しないなら, GPL ライセンスにする必要はない. GPL のプログラムの出力結果なども同様だ.また,私的な範囲の利用も頒布に当たらないため, GPL を適用する必要はない.これは,以下の GPL の FAQ の回答を読むのがいいだろう:</p>
<ul class="simple">
<li><a class="reference external" href="https://www.gnu.org/licenses/gpl-faq.html#GPLStaticVsDynamic">(GPLの)及ぶ作品に対し、静的 vs 動的にリンクされたモジュールについて、GPLには異なる要求がありますか?</a></li>
<li><a class="reference external" href="https://www.gnu.org/licenses/gpl-faq.html#GPLModuleLicense">GPLの及ぶプログラムに対してあるモジュールを追加する場合、わたしのモジュールにもライセンスとしてGPLを適用しなければなりませんか?</a></li>
<li><a class="reference external" href="https://www.gnu.org/licenses/gpl-faq.html#InternalDistribution">一つの組織あるいは会社で複数のコピーを作成して使うことは「配布」となりますか?</a></li>
<li><a class="reference external" href="https://www.gnu.org/licenses/gpl-faq.html#CanIUseGPLToolsForNF">自由でないプログラムを開発するために、GNU EmacsのようなGPLの及ぶエディタを使っても良いでしょうか? GCCのようなGPLの及ぶツールを使って自由でないプログラムをコンパイルすることはできますか?</a></li>
</ul>
<p>なので,結合したものを頒布しないなら, GPL ライセンスを使う必要はない.ただ,注意して欲しいのは,自分が頒布しなくても他人が頒布するかもしれないことに気をつけなければいけないということだ.</p>
</div>
<div class="section" id="auto-id-7">
<h2>ライセンス運用時の注意<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>で,なんで GPL について先に話したかというと,こいつやたらと運用がめんどくさい.これが,最近忌避されてる理由でもある.まあ,他にも幾つか運用に注意が必要なライセンスはあるので,知ってるライセンスの運用方法をちょっとまとめとく.</p>
<div class="section" id="auto-id-8">
<h3>GPL との共存<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>GPL は先に言ったように,追加の制限を設けてはいけない.ただ, GPL より緩いライセンスとの共存は可能だ.多くの場合手間との兼ね合いから,自身のソースコードには GPL より緩いライセンスを使いそのライセンスファイルを置き, GPL 下のライブラリのライセンスファイルを消さないで一緒にソースコードとして含めて頒布すると, GPL 下のライブラリのライセンスファイルの条項により全体が自動的に GPL と解釈されて GPL ライセンスの下での頒布になるという解釈がされる,というのが慣例だと思う.この慣例は,基本的に運用の問題なので, GPL でそういう運用が想定されてるわけではないけど,そうなってるのが現状という感じ.なので, GPL との共存を見据えた基本的な運用方法は,</p>
<ol class="arabic simple">
<li>GPL または GPL より緩いライセンスで自身のコードを配布する.</li>
<li>コンパイル済みバイナリなどを配布するのなら,インストーラなどでこのプログラムは GPL 下で配布されること,ソースコードのリンク先を表示し,使用者の同意を得る.</li>
</ol>
<p>みたいなのがいいだろう.ライブラリの場合, GPL のライブラリに依存してることを明記しておくと親切だろうが,別に明記しなくてもいい.とりあえずの絶対条件は,</p>
<ul class="simple">
<li>GPL より緩いライセンスでコードを配布すること.</li>
<li>ソースコードをダウンロードできるようにしておくこと</li>
</ul>
<p>だ.自身でバイナリを配布しないなら,後は再頒布者の責任となるだろう.で,具体的に GPL より緩いライセンスってどういうものがあるのかなんだけど, GPL 2.0 と GPL 3.0 で共存できる範囲が異なり,</p>
<ul class="simple">
<li>GPL 2.0 or 3.0: LGPL 2.1 / 修正BSD / MIT / MPL 2.0</li>
<li>GPL 3.0: Apache 2.0 / LGPL 3.0</li>
</ul>
<p>という感じ. GPL 2.0 より GPL 3.0 の方が制限が強いので, GPL 2.0 と GPL 3.0 は共存できない.逆にいえば GPL 2.0 と共存するなら GPL 3.0 とも共存する.なお, GPL 2.0 には <tt class="docutils literal">or later</tt> という文面を加えることにより GPL 3.0 でもライセンスとして許容するという慣例がある.この場合, GPL 3.0 扱いにできるので, Apache 2.0 とかとも共存できる.この共存できるというのを, OSS ライセンス界隈では,ライセンス互換性と呼ぶことがある.</p>
</div>
<div class="section" id="mpl">
<h3>MPL の運用<a class="headerlink" href="#mpl" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>MPL 2.0 は,かなり特殊なライセンスで, GPL と同じようにコピーレフトなんだけど,その効力はファイル単位と規定されてる.なので,基本的にはファイル単位で GPL と同じことを気をつければいい. MPL 2.0 のライブラリに依存するプログラムを作ってそれをコンパイルしたバイナリを配布する場合は, MPL 2.0 のライブラリのファイルは公開しなきゃいけない.ただ,そのファイル以外については特に制約なくどんなライセンスを使ってもいい.なので,かなりコピーレフトの範囲に制限がかかる.</p>
<p>MPL 2.0 を自身のコードに使いたい場合は, <a class="reference external" href="https://www.mozilla.org/en-US/MPL/2.0/FAQ/#apply">https://www.mozilla.org/en-US/MPL/2.0/FAQ/#apply</a> に書いてある通り,ライセンスを適用したい範囲に</p>
<pre class="literal-block">
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
</pre>
<p>という文面をコメントで入れればいい.ただ運用上めんどくさい場合,あまり推奨ではないが,適用する範囲を明示した注記をどこか目立つところに書くだけでも良いことになっている <a class="footnote-reference" href="#mpl-notice-exception" id="auto-id-9">[3]</a> .</p>
<p>ところで, MPL 2.0 は, GPL との結合に対して特別の条項を設けている.本来, MPL はその保護下にあるファイルを MPL で提供しなければいけないが, GPL は結合したものを GPL で提供する必要がある.なので, MPL 保護下のファイルは GPL に関してはライセンスを切り替えてもいいことになっている.もっと厳密にいうと,切り替えていいライセンスは <a class="reference external" href="https://www.mozilla.org/en-US/MPL/2.0/#definitions">MPL の 1. Definition</a> の 1.12. "Secondary License" で述べられている,以下の 4 つだ.</p>
<ul class="simple">
<li>GNU General Public License, Version 2.0</li>
<li>GNU Lesser General Public License, Version 2.1</li>
<li>GNU Affero General Public License, Version 3.0</li>
<li>以上のライセンスの上位バージョン</li>
</ul>
<p>よって, MPL 2.0 は GPL 2.0 , GPL 3.0 をはじめとする GPL 系のライセンスと互換性があることになる.</p>
</div>
<div class="section" id="auto-id-10">
<h3>デュアルライセンス<a class="headerlink" href="#auto-id-10" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>ライセンスは何も単一のものを提供する必要はない. 2 種類のライセンスを提供するデュアルライセンス,または 2 種類以上のライセンスを提供するマルチライセンスも選択肢として,実際に使用されている方法だ. Mozilla Firefox は元々 GPL への切り替え条項がなかった時代は, GPL / LGPL / MPL のトリプルライセンスで提供されていた.この名残で, MPL 2.0 の Secondary License 条項はトリプルライセンス条項とも呼ばれている.</p>
<p>デュアルライセンスというのはよく勘違いされがちだけど, 2 つのライセンスを二重に適用するものではなく,どちらのライセンスを使うか,使用者が選べるライセンス方式だ.これは, GPL 2.0 のライブラリと組み合わせる場合に,片方を緩いライセンスにしておくことで互換性問題を回避するのに便利だ.ただそのようなテクニック以上の意味もある. MPL や GPL は,著作権主張は存在せず代わりにライセンス規則が後々までずっと効いてくる.対して,通常の OSS ライセンスは著作権を主張する代わりに改変や再頒布に対して著作権表記ぐらいしか制約を課さない.この 2 つをデュアルライセンスで提供することで,著作者の権利を主張し尊重したい人,自由にプログラムを作ることを促進したい人はコピーライトの制約の緩いライセンスを, OSS の共同体の一員として特に著作権主張をせずにコントリビュートをしたい人, OSS の公開の場での技術共有に価値があると思う人はコピーレフトなライセンスを選択する,その選択肢を提供することで,使用者の価値観や文化を尊重しながら使用許諾を与える為の方法という面もある.</p>
<p>デュアルライセンスは,使われてるとこでは使われていて, Rust は MIT / Apache 2.0 のデュアルライセンスになっている. Perl は GPL Version 1 以上と Artistic ライセンスとのマルチライセンスだ.</p>
</div>
<div class="section" id="auto-id-11">
<h3>ライセンスの変更<a class="headerlink" href="#auto-id-11" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>ライセンスは,著作者から使用者への使用許諾だと冒頭で言った.でも, OSS では著作者というのは一定に定まらない場合が多い.パッチの提供があった場合,その人も著作者の一人になる. Apache 2.0 では,コントリビューションに対しての権利が明確に書かれており,そのライセンスで書かれている著作権表記者に権利が移譲されることになるが,それでも著作者の一人であることには変わりない.そう考えた時に,ライセンスというのは,著作権表記者が代表者となり,コントリビュータに「この使用許諾を満たす人があなたの著作物を使いますよ,いいですか?」という条件で契約を結び,使用者に「この使用許諾を満たすなら,使用していいですよ」という条件で契約を結ぶ, 2 者の契約者がいることになる.ライセンスの変更は,この 2 者どちらに対してもの契約条件の変更になる.</p>
<p>契約条件の変更というのは結構大きいことだと思う.なので,ライセンスを変更する際は 2 者に良く説明することが大事だ.特にコントリビュータは,自分の著作物がコントリビュート当時のライセンスで提供されるという契約で,代表者に預けている.なので,今までのコントリビュータと良く話し合って決めるというのが通例だと思う. OpenSSL は 3.0 にするタイミングで, Apache 2.0 にライセンスを変更してるけど,この際は過去のコントリビュータと連絡を取り,連絡が取れなかったコントリビュータの書いた部分は書き直しを行なっている <a class="footnote-reference" href="#openssl-is-relicensing" id="auto-id-12">[4]</a>.これは,ここまでするのかと驚く人もいると思うけど,個人的にはコントリビュータの作品を尊重し,契約を履行する最良の手段だと思う.</p>
<p>その上でライセンス変更をする際は,ライセンスを変更した理由と差分をどっかにまとめておき, README に一定期間注意書きを追加するのがいいと思う.ただ,ライセンスというのは著作者が出す使用許諾なのだから,契約条件の変更自体は良くあることだし,変えたい理由があるならいつだって変えてもいいと思う.もちろん,その変更は今までのバージョンには適用しないのが通例で,メジャーバージョンの変更ぐらいは良くやられる.大事なことは,契約条件の変更があったことを今までの契約者に伝え,互いに了解することだと思う.</p>
</div>
</div>
<div class="section" id="auto-id-13">
<h2>個人的な運用法<a class="headerlink" href="#auto-id-13" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>で,以上のことを踏まえて個人的なライセンス運用の際のお気持ちと,最近の運用の仕方を書いておく.</p>
<div class="section" id="auto-id-14">
<h3>よくライセンス界隈で思うこと<a class="headerlink" href="#auto-id-14" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>OSS ライセンスでは格式張ったテンプレが横行してるせいで,文面の細部に注意がいきがちなんだけど,本来契約が主で,ライセンスというのは契約において単なる書面の一つにすぎない.よく, OSS ライセンスに対して解釈の議論が起きることがあるけれど,本来契約者の解釈こそが最も大事で,その解釈で契約を取り交わしたのに第三者が契約内容にとやかく言うのはどうなんだろうと思う.出回っているテンプレは,良く契約上取り交す条件があって,互いに信頼しているからこそ,その信頼を壊さない為書いておいた方がいいと先人たちが判断したことが,書かれてるものに過ぎなくて,このテンプレにこだわって契約を蔑ろにする行為は本末転倒だと個人的には思う.</p>
<p>ライセンスを自作するのは,それこそ契約の際相手の不信感を煽るという意味であまり推奨されないが,それでも自分が入れておいた方がいいと思う条件があるなら,その条件をライセンスに含めていいと思うし,その旨をしっかり契約時に説明すればいい.大事なのは,ライセンスに書かれていることではなく契約相手と自分が納得のいく形で契約を行うことだ.そんぐらいの気持ちで付き合っていくのが,いい気がする.逆に,契約というのはライセンスが全てじゃなくて信頼が全てだ.ライセンスは信頼を得るための一角であって,このライセンスの運用が信頼を裏切るものならば,そもそもライセンスを用意する意義はないと思う.そこら辺を意識して,自分なりに運用していけるなら,それがベストなんじゃないかと.</p>
</div>
<div class="section" id="auto-id-15">
<h3>最近良く使ってる方式<a class="headerlink" href="#auto-id-15" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>で,最近個人的に良く使ってる方式は,以下のやつ:</p>
<ol class="arabic simple">
<li>通常は, MPL 2.0 / Apache 2.0 のデュアルライセンス</li>
<li>GPL への組み合わせが前提の場合, MPL 2.0 / MIT のデュアルライセンス</li>
<li>ライブラリとかではなく特に再頒布を意図していないものは, Apache 2.0 のシングルライセンス</li>
</ol>
<p>MPL は,ライセンス表記をコメントでファイルごとに書くのが強く推奨されてるけど,運用上それだと不都合も多いし見栄えも良くない.なので, MPL 2.0 / Apache 2.0 の構成にする際は,以下の文面を <tt class="docutils literal">NOTICE.md</tt> って名前で加えることにしている:</p>
<pre class="literal-block">
# Notice
You must read this notice before distributing any copies of files
of this project or module.
## License
This project or module is dual-licensed under the Mozilla Public
License 2.0 (at http://mozilla.org/MPL/2.0/) and the Apache License
2.0 (at https://www.apache.org/licenses/LICENSE-2.0). You can choose
which one to use.
### The Mozilla Public License Notice
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
By definition 1.4 of the Mozilla Public License 2.0, the above notice
means all of files of this project or module are included in
"Covered Software". If anyone distributes just a copy of a file of
this project or module by the Mozilla Public License 2.0, he or she
may add this notice by any reasonable method (e.g. as a comment)
instead of attached this document.
</pre>
<p>で, MPL 2.0 の文面を <tt class="docutils literal"><span class="pre">LICENSE.MPL-2.0</span></tt> , Apache 2.0 の文面に著作権保持者の名前を入れたものを <tt class="docutils literal"><span class="pre">LICENSE.Apache-2.0</span></tt> , SPDX 表記でデュアルライセンスを表す <tt class="docutils literal"><span class="pre">Apache-2.0</span> OR <span class="pre">MPL-2.0</span></tt> と書かれたものを <tt class="docutils literal">LICENSE.txt</tt> という名前で置いて, README に NOTICE を読んでと書く感じ.</p>
<p>NOTICE の後半部分に書いてあるのは,「上に書いてあることは,うちのプロジェクトのファイルは MPL 2.0 での "Covered Software" であることを意味しますよ.もし,うちのファイルを一部抜き出して MPL 2.0 ライセンスの下で配布したい場合,上の注記を何らかの形で含めてくださいね」って感じ.</p>
</div>
</div>
<div class="section" id="auto-id-16">
<h2>まとめ<a class="headerlink" href="#auto-id-16" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ライセンスについて,自分が持ってる知識と個人的な解釈,運用方法を書いた.</p>
<p>専門家じゃないので,全然偉そうなことは言えないんだけど, OSS ライセンスのそもそもの意義に立ち返って運用していくのは,大事な気がする.そこら辺,なんかいい感じにやっていきたい.</p>
<p>後,読み直してみて思ったけど,この記事かなり GPL へのネガキャンがひどいので,そこら辺は注意してくれ (これをまとめで書くあたり,確信犯な感じがある) .</p>
<table class="docutils footnote" frame="void" id="copyleft-is-minor" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[1]</a></td><td>よくこの特徴で OSS ライセンスを 2 分している人を見かけるのだが,コピーレフトなんて GPL 系のライセンスぐらいしか設けてないやろ...</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="image-copyleft" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[2]</a></td><td>イメージとしては,最大値と最小値が共に GPL になる.元々, GPL より小さいものを GPL と組み合わせると GPL になり,それより大きくもできない感じ.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="mpl-notice-exception" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-9">[3]</a></td><td>MPL 2.0 の Exhibit A にその旨が書いてある.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="openssl-is-relicensing" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-12">[4]</a></td><td><a class="reference external" href="https://www.openssl.org/blog/blog/2017/03/22/license/">https://www.openssl.org/blog/blog/2017/03/22/license/</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/about-oss-licenses.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/about-oss-licenses.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Scala コードの裏側2019-04-24T05:04:52+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-24:/blog/posts/2019/04/scala-compile-inside/<p>先日, Scala コードの裏側について幾つか話を聞いた.で,気になったので実際に JVM コードを出して,色々見てみることにした.なお,当方 Scala 初心者 …</p><p>先日, Scala コードの裏側について幾つか話を聞いた.で,気になったので実際に JVM コードを出して,色々見てみることにした.なお,当方 Scala 初心者なので,おそらくかなり間違いを含んでるのと,普段使いの感覚からは離れてる部分はあると思うので,そこら辺は注意して読んでくれって感じ.</p>
<div class="section" id="auto-id-1">
<h2>Scala コンパイラの概要<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Scala コンパイラが実際どういう処理をしてるのか知らなかったので,まずはその辺を調べた. Scala は,プログラムを複数のフェーズに分けてコンパイルし,最終的に JVM のコードを吐き出すっぽい.コンパイルフェーズは,以下のコマンドで見れるっぽい <a class="footnote-reference" href="#how-to-install-scalac" id="auto-id-2">[1]</a>:</p>
<pre class="literal-block">
$ scalac -Xshow-phases
phase name id description
---------- -- -----------
parser 1 parse source into ASTs, perform simple desugaring
namer 2 resolve names, attach symbols to named trees
packageobjects 3 load package objects
typer 4 the meat and potatoes: type the trees
patmat 5 translate match expressions
superaccessors 6 add super accessors in traits and nested classes
extmethods 7 add extension methods for inline classes
pickler 8 serialize symbol tables
refchecks 9 reference/override checking, translate nested objects
uncurry 10 uncurry, translate function values to anonymous classes
fields 11 synthesize accessors and fields, add bitmaps for lazy vals
tailcalls 12 replace tail calls by jumps
specialize 13 @specialized-driven class and method specialization
explicitouter 14 this refs to outer pointers
erasure 15 erase types, add interfaces for traits
posterasure 16 clean up erased inline classes
lambdalift 17 move nested functions to top level
constructors 18 move field definitions into constructors
flatten 19 eliminate inner classes
mixin 20 mixin composition
cleanup 21 platform-specific cleanups, generate reflective calls
delambdafy 22 remove lambdas
jvm 23 generate JVM bytecode
terminal 24 the last phase during a compilation run
</pre>
<p>各フェーズは, <a class="reference external" href="https://www.scala-lang.org/api/2.12.x/scala-reflect/scala/reflect/api/Trees.html">scala.reflect.apis.Trees</a> に定義されている構成子を使って作成された構文木を,変換していく.それぞれのフェーズが出力する木は,次のようにして見れる:</p>
<pre class="literal-block">
$ cat src/TestSource.scala
object TestSource {
def testSource(a: Long): Long = {
val b = a + 1
b
}
}
$ scalac -Ystop-after:parser -Xprint:parser src/TestSource.scala
[[syntax trees at end of parser]] // TestSource.scala
package <empty> {
object TestSource extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
def testSource(a: Long): Long = {
val b = a.$plus(1);
b
}
}
}
</pre>
<p>また,構文木を GUI で見るためのオプションも用意されている:</p>
<pre class="literal-block">
$ cat src/TestSource.scala
object TestSource {
def testSource(a: Long): Long = {
val b = a + 1
b
}
}
$ scalac -Ystop-after:parser -Ybrowse:parser src/TestSource.scala
</pre>
<p>こうすると,以下の画面が表示される:</p>
<img alt="構文木をツリー表示する GUI 画面." src="https://mizunashi-mana.github.io/blog/posts/2019/04/scala-compile-inside/scala-compile-inside/scala-browse-example.png"/>
<p>では, Scala コードが実際にどういう JVM コードを出すのか見ていきたいと思う.なお,試した環境は,以下の通り:</p>
<table border="1" class="docutils">
<colgroup>
<col width="39%"/>
<col width="61%"/>
</colgroup>
<tbody valign="top">
<tr><td>Scala のバージョン</td>
<td>2.12.8</td>
</tr>
<tr><td>Java Runtime のバージョン</td>
<td>Java(TM) SE Runtime Environment 1.8.0_131</td>
</tr>
<tr><td>Java Hotspot のバージョン</td>
<td>Java HotSpot(TM) 64-Bit Server VM 25.131</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="auto-id-3">
<h2>末尾呼び出し最適化<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Java は末尾呼び出し最適化をしないことで有名だ <a class="footnote-reference" href="#why-java-dont-have-tco" id="auto-id-4">[2]</a>.だけど, Scala は末尾呼び出し最適化を行う.具体的にコードを見てみる:</p>
<pre class="literal-block">
$ cat src/TailCallOpt.scala
object TailCallOpt {
def tailCallFunc(a: Long): Long = {
if (a > 10) a else tailCallFunc(a + 1)
}
}
$ scalac -Ystop-after:tailcalls -Xprint:fields,tailcalls src/TailCallOpt.scala
[[syntax trees at end of fields]] // TailCallOpt.scala
package <empty> {
object TailCallOpt extends Object {
def <init>(): TailCallOpt.type = {
TailCallOpt.super.<init>();
()
};
def tailCallFunc(a: Long): Long = if (a.>(10))
a
else
TailCallOpt.this.tailCallFunc(a.+(1))
}
}
[[syntax trees at end of tailcalls]] // TailCallOpt.scala
package <empty> {
object TailCallOpt extends Object {
def <init>(): TailCallOpt.type = {
TailCallOpt.super.<init>();
()
};
def tailCallFunc(a: Long): Long = {
<synthetic> val _$this: TailCallOpt.type = TailCallOpt.this;
_tailCallFunc(_$this: TailCallOpt.type, a: Long){
if (a.>(10))
a
else
_tailCallFunc(TailCallOpt.this, a.+(1).asInstanceOf[Long]()).asInstanceOf[Long]()
}
}
}
}
</pre>
<p>この最適化は名前の通り, <tt class="docutils literal">tailcalls</tt> フェーズで行われる.実は Scala 内部では <a class="reference external" href="https://www.scala-lang.org/api/2.12.x/scala-reflect/scala/reflect/api/Trees$LabelDef.html">ラベル式</a> という構文が存在する. Scala のプログラム的にはこの式は書けないが,構文木上は用意されていて,最終的にジャンプに変換される.今回のも, <tt class="docutils literal">tailCallFunc</tt> の中身はこのラベル式を使って変換されている.以下の部分がそう:</p>
<pre class="literal-block">
_tailCallFunc(_$this: TailCallOpt.type, a: Long) {
if (a.>(10))
a
else
_tailCallFunc(TailCallOpt.this, a.+(1).asInstanceOf[Long]()).asInstanceOf[Long]()
}
</pre>
<p>実際に,対応する JVM のバイトコードを見てみる:</p>
<pre class="literal-block">
$ scalac src/TailCallOpt.scala
$ ls -D
'TailCallOpt$.class' TailCallOpt.class src/
$ javap -v -c 'TailCallOpt$.class'
...
public long tailCallFunc(long);
descriptor: (J)J
flags: ACC_PUBLIC
Code:
stack=4, locals=3, args_size=2
0: lload_1
1: ldc2_w #16 // long 10l
4: lcmp
5: ifle 12
8: lload_1
9: goto 19
12: lload_1
13: lconst_1
14: ladd
15: lstore_1
16: goto 0
19: lreturn
...
</pre>
<p><tt class="docutils literal">javap</tt> は Java の逆アセンブラ. <tt class="docutils literal"><span class="pre">-v</span></tt> をつけると詳細に情報を表示してくれる.で,コードの読み方だけど,まずは JVM の基本事項から:</p>
<ul class="simple">
<li>メソッドごとに <a class="reference external" href="https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.7.13">ローカル変数テーブル</a> が用意されている.初期状態では,メソッドの引数が順番に入る.なお, <tt class="docutils literal">double</tt> と <tt class="docutils literal">long</tt> はテーブルの 2 行分領域を取る.</li>
<li>定数は,クラスそれぞれに用意されている <a class="reference external" href="https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-4.html#jvms-4.4">定数プール</a> に,添字と型付きで格納される.添字は, <tt class="docutils literal">#[数字]</tt> の形で表される.</li>
<li>JVM は 1 スタックで動く.</li>
</ul>
<p>他にも重要なことは一杯あるんだけど,とりあえずコードを読むために上のことは押さえておいてくれって感じ.で,具体的な命令の内容だけど,以下のようになる:</p>
<pre class="literal-block">
// ローカル変数テーブルの 1 番目を, long 値としてスタックに積む
0: lload_1
// 定数プールから値 (``#16`` にはコメントで書かれてる通り, ``10L`` が入っている) を呼び出し,スタックに積む
1: ldc2_w #16 // long 10l
// スタックから 2 要素取り出し, long 値として比較した結果をスタックに積む
4: lcmp
// 比較結果が「以下」であれば, 12 バイト目に飛ぶ
5: ifle 12
// ローカル変数テーブルの 1 番目を, long 値としてスタックに積む
8: lload_1
// 19 バイト目に飛ぶ
9: goto 19
// ローカル変数テーブルの 1 番目を, long 値としてスタックに積む
12: lload_1
// long 値 1 を,スタックに積む
13: lconst_1
// スタックから 2 要素取り出し,加算した結果をスタックに積む
14: ladd
// スタックから 1 要素取り出し, long 値としてローカル変数テーブルの 1 番目に格納する
15: lstore_1
// 0 バイト目に飛ぶ
16: goto 0
// スタックに返り値として long 値を残して,呼び出し元に戻る
19: lreturn
</pre>
<p>もう少し分かりやすいよう, C 言語風に書き直してみると,以下のようになる:</p>
<pre class="literal-block">
long tailCallFunc(void *a0, long a1) {
const long tmp = 10L;
START:
if (a1 <= tmp) {
goto END;
}
a1 = a1 + 1;
goto START;
END:
return a1;
}
</pre>
<p>完全に一対一対応するわけではないが,大体やってることはこんな感じ.最初の引数は, <tt class="docutils literal">this</tt> が入ることに注意.なんしろ,末尾再帰は <tt class="docutils literal">goto</tt> を使ってただのループに変換されてることが分かると思う.なお, <tt class="docutils literal">while</tt> などもラベル式に変換された後,同じように <tt class="docutils literal">goto</tt> を使った JVM コードが出される. Scala だと, <tt class="docutils literal">tailrec</tt> アノテーションを使うことで,末尾呼び出し最適化が行われる形になってるかチェックすることもできる:</p>
<pre class="literal-block">
import scala.annotation.tailrec
object TailCallOpt {
@tailrec
def tailCallFunc(a: Long): Long = {
if (a > 10) a else tailCallFunc(a + 1)
}
}
</pre>
</div>
<div class="section" id="auto-id-8">
<h2>大域脱出<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Scala には,大域リターン(non local return)という機能がある.実は僕はこの機能を知らなかったんだけど,以下のようなやつ:</p>
<pre class="literal-block">
def func(): Long = {
List(1, 2, 3) foreach { x =>
if (x > 2) return 1
}
return 0
}
</pre>
<p><tt class="docutils literal">foreach</tt> メソッドが受け取っている無名関数の中で <tt class="docutils literal">return</tt> を書くと,外側のメソッドが抜ける.ただ, Java では C で言う所の <tt class="docutils literal">setjmp</tt> / <tt class="docutils literal">longjmp</tt> 機能がない.これを実際にどう実現するかなんだけど,有名な方法があって,スタックトレースを消した例外をハンドリングする. Scala ではこの方法が用いられてる <a class="footnote-reference" href="#i-knew-it-recently" id="auto-id-9">[3]</a> .実際にコード生成を見てみると以下のようになる:</p>
<pre class="literal-block">
$ cat src/NonLocalReturn.scala
object NonLocalReturn {
def nonLocalReturn(): Long = {
List(1L, 2L, 3L) foreach { x =>
if (x > 2) return x
}
return 0
}
}
$ scalac -Ystop-after:uncurry -Xprint:refchecks,uncurry src/NonLocalReturn.scala
[[syntax trees at end of refchecks]] // NonLocalReturn.scala
package <empty> {
object NonLocalReturn extends scala.AnyRef {
def <init>(): NonLocalReturn.type = {
NonLocalReturn.super.<init>();
()
};
def nonLocalReturn(): Long = {
scala.collection.immutable.List.apply[Long](1L, 2L, 3L).foreach[Unit](((x: Long) => if (x.>(2))
return x
else
()));
return 0L
}
}
}
[[syntax trees at end of uncurry]] // NonLocalReturn.scala
package <empty> {
object NonLocalReturn extends Object {
def <init>(): NonLocalReturn.type = {
NonLocalReturn.super.<init>();
()
};
def nonLocalReturn(): Long = {
<synthetic> val nonLocalReturnKey1: Object = new Object();
try {
scala.collection.immutable.List.apply[Long](scala.Predef.wrapLongArray(Array[Long]{1L, 2L, 3L})).foreach[Unit]({
final <artifact> def $anonfun$nonLocalReturn(x: Long): Unit = if (x.>(2))
throw new scala.runtime.NonLocalReturnControl[Long](nonLocalReturnKey1, x)
else
();
((x: Long) => $anonfun$nonLocalReturn(x))
});
return 0L
} catch {
case (ex @ (_: scala.runtime.NonLocalReturnControl[Long @unchecked])) => if (ex.key().eq(nonLocalReturnKey1))
ex.value()
else
throw ex
}
}
}
}
</pre>
<p>この変換は <tt class="docutils literal">uncurry</tt> フェーズで行われるっぽい.大域リターンが, <tt class="docutils literal">NonLocalReturnControl</tt> 例外のハンドリングに変換されていることが分かる. <tt class="docutils literal">return</tt> は <tt class="docutils literal">NonLocalReturnControl</tt> の <tt class="docutils literal">throw</tt> に変換し,外側で <tt class="docutils literal">catch</tt> してその値を <tt class="docutils literal">return</tt> している. <tt class="docutils literal">NonLocalReturnControl</tt> はスタックトレースを生成しないために, <tt class="docutils literal">fillInStackTrace</tt> を書き換えてる.定義は以下のようになっている <a class="footnote-reference" href="#non-local-return-control-definition" id="auto-id-10">[4]</a>:</p>
<pre class="literal-block">
import scala.util.control.ControlThrowable
class NonLocalReturnControl[@specialized T](val key: AnyRef, val value: T) extends ControlThrowable {
final override def fillInStackTrace(): Throwable = this
}
</pre>
<p>ところで余談だけど, Scala の無名関数はこの後ラムダリフティング (lambdalift) によって final method に変換され,ラムダ除去 (delambdafy) によって Java の Single Abstract Method (SAM) が使える形に変換される.今回の例をそのまま使うと,例外ハンドリングによってかなりノイズが大きくなるので,もう少し簡略化した例で示すと以下の感じ:</p>
<pre class="literal-block">
$ cat src/Lambda.scala
object Lambda {
def func(a: Long) {
List(1L, 2L, 3L) foreach { x => x + a }
}
}
$ scalac -Ystop-after:jvm -Xprint:uncurry,lambdalift,delambdafy,jvm src/Lambda.scala
[[syntax trees at end of uncurry]] // Lambda.scala
package <empty> {
object Lambda extends Object {
def <init>(): Lambda.type = {
Lambda.super.<init>();
()
};
def func(a: Long): Unit = scala.collection.immutable.List.apply[Long](scala.Predef.wrapLongArray(Array[Long]{1L, 2L, 3L})).foreach[Long]({
final <artifact> def $anonfun$func(x: Long): Long = x.+(a);
((x: Long) => $anonfun$func(x))
})
}
}
[[syntax trees at end of lambdalift]] // Lambda.scala
package <empty> {
object Lambda extends Object {
def <init>(): Lambda.type = {
Lambda.super.<init>();
()
};
def func(a: Long): Unit = scala.collection.immutable.List.apply(scala.Predef.wrapLongArray(Array[Long]{1L, 2L, 3L})).foreach({
((x: Long) => Lambda.this.$anonfun$func$1(a, x))
});
final <artifact> private[this] def $anonfun$func$1(a$1: Long, x: Long): Long = x.+(a$1)
}
}
[[syntax trees at end of delambdafy]] // Lambda.scala
package <empty> {
object Lambda extends Object {
def func(a: Long): Unit = scala.collection.immutable.List.apply(scala.Predef.wrapLongArray(Array[Long]{1L, 2L, 3L})).foreach({
$anonfun(a)
});
final <static> <artifact> def $anonfun$func$1(a$1: Long, x: Long): Long = x.+(a$1);
def <init>(): Lambda.type = {
Lambda.super.<init>();
()
}
}
}
[[syntax trees at end of jvm]] // Lambda.scala: tree is unchanged since delambdafy
</pre>
<p><tt class="docutils literal">$anonfun(a)</tt> が <tt class="docutils literal">$anonfun$func$1</tt> final method を使った SAM の呼び出しに置換される.うちの環境だと,最終的に次のような JVM コードが出される:</p>
<pre class="literal-block">
$ javap -p -v -c 'Lambda$.class'
...
public void func(long);
descriptor: (J)V
flags: ACC_PUBLIC
Code:
stack=7, locals=3, args_size=2
0: getstatic #25 // Field scala/collection/immutable/List$.MODULE$:Lscala/collection/immutable/List$;
3: getstatic #30 // Field scala/Predef$.MODULE$:Lscala/Predef$;
6: iconst_3
7: newarray long
9: dup
10: iconst_0
11: lconst_1
12: lastore
13: dup
14: iconst_1
15: ldc2_w #31 // long 2l
18: lastore
19: dup
20: iconst_2
21: ldc2_w #33 // long 3l
24: lastore
25: invokevirtual #38 // Method scala/Predef$.wrapLongArray:([J)Lscala/collection/mutable/WrappedArray;
28: invokevirtual #42 // Method scala/collection/immutable/List$.apply:(Lscala/collection/Seq;)Lscala/collection/immutable/List;
31: lload_1
32: invokedynamic #64, 0 // InvokeDynamic #0:apply$mcJJ$sp:(J)Lscala/runtime/java8/JFunction1$mcJJ$sp;
37: invokevirtual #70 // Method scala/collection/immutable/List.foreach:(Lscala/Function1;)V
40: return
...
BootstrapMethods:
0: #60 invokestatic java/lang/invoke/LambdaMetafactory.altMetafactory:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
Method arguments:
#44 (J)J
#49 invokestatic Lambda$.$anonfun$func$1:(JJ)J
#44 (J)J
#50 3
#51 1
#53 scala/Serializable
1: #86 invokestatic scala/runtime/LambdaDeserialize.bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/invoke/CallSite;
...
</pre>
<p>詳しい説明は省略するが,注目して欲しいのは 32 バイト目の <tt class="docutils literal">invokedynamic</tt> で呼ばれてるやつ. <tt class="docutils literal">invokedynamic</tt> は SAM 向けに Java8 から新たに導入された命令で <a class="footnote-reference" href="#invokedynamic-is-in-java7-yet" id="auto-id-11">[5]</a>,1番目に SAM の元となるクラスメソッド,2番目にブートストラップメソッドの番号を受け取って,ブートストラップメソッドから生成したメソッドを呼び出す.なお, 2 回目からはブートストラップメソッドは呼び出されず,作ったメソッドを直接呼び出すことで効率が良くなるとかがあるらしい.なお,ここで SAM の元となるオブジェクトに <tt class="docutils literal">scala/runtime/java8/JFunction1$mcJJ$sp</tt> というのが指定されているのが分かると思う. Scala では生成する SAM の型によって幾つかテンプレートを用意しているようで, <a class="reference external" href="scala/runtime/java8/JFunction1$mcJJ$sp">JFunction1$mcJJ$sp</a> はメソッドの型が <tt class="docutils literal">(v1: Long): Long</tt> となるやつに対するテンプレートになっている.こうすると何が良いのかいまいち分からないけど,きっと効率が良くなるか <tt class="docutils literal">invokedynamic</tt> の制約かなんかなんだろうなあ (適当) .</p>
</div>
<div class="section" id="lazy-val">
<h2>lazy val のパフォーマンス<a class="headerlink" href="#lazy-val" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>最後に <tt class="docutils literal">lazy val</tt> について.これは,話を聞く前から気になってたんだけど, Scala の <tt class="docutils literal">lazy val</tt> は大変遅いという噂をよく聞く.で,具体的にどんくらい遅いのか,何が原因なのかをちょっと調べてみた.まず, <tt class="docutils literal">lazy val</tt> は,最終的にどのようなコードに変換されるのかを見てみる.まず, Scala の各フェーズの変換から:</p>
<pre class="literal-block">
$ cat src/LazyVal.scala
object LazyVal {
def func(a: Int): Int = {
lazy val v = a + 1
v + 2
}
}
$ scalac -Ystop-after:jvm -Xprint:uncurry,fields,jvm src/LazyVal.scala
[[syntax trees at end of uncurry]] // LazyVal.scala
package <empty> {
object LazyVal extends Object {
def <init>(): LazyVal.type = {
LazyVal.super.<init>();
()
};
def func(a: Int): Int = {
<stable> <accessor> lazy val v: Int = a.+(1);
v().+(2)
}
}
}
[[syntax trees at end of fields]] // LazyVal.scala
package <empty> {
object LazyVal extends Object {
def <init>(): LazyVal.type = {
LazyVal.super.<init>();
()
};
def func(a: Int): Int = {
lazy <artifact> val v$lzy: scala.runtime.LazyInt = new scala.runtime.LazyInt();
<artifact> private def v$lzycompute(): Int = v$lzy.synchronized[Int](if (v$lzy.initialized())
v$lzy.value()
else
v$lzy.initialize(a.+(1)));
lazy def v(): Int = if (v$lzy.initialized())
v$lzy.value()
else
v$lzycompute();
v().+(2)
}
}
}
[[syntax trees at end of jvm]] // LazyVal.scala
package <empty> {
object LazyVal extends Object {
def func(a: Int): Int = {
lazy <artifact> val v$lzy: scala.runtime.LazyInt = new scala.runtime.LazyInt();
LazyVal.this.v$1(v$lzy, a).+(2)
};
final <static> <artifact> private[this] def v$lzycompute$1(v$lzy$1: scala.runtime.LazyInt, a$1: Int): Int = v$lzy$1.synchronized(if (v$lzy$1.initialized())
v$lzy$1.value()
else
v$lzy$1.initialize(a$1.+(1)));
final <static> lazy private[this] def v$1(v$lzy$1: scala.runtime.LazyInt, a$1: Int): Int = if (v$lzy$1.initialized())
v$lzy$1.value()
else
LazyVal.this.v$lzycompute$1(v$lzy$1, a$1);
def <init>(): LazyVal.type = {
LazyVal.super.<init>();
()
}
}
}
</pre>
<p><tt class="docutils literal">Int</tt> 型の <tt class="docutils literal">lazy val</tt> の場合素直に,初期化されているかチェックして初期化されていなければ計算を実行し結果を保存して返す,されていれば保存した値をそのまま返すみたいなことをするオブジェクトを返してるっぽい.ただ,初期化は複数のスレッドから呼び出されると競合が起きるので <tt class="docutils literal">synchronized</tt> を指定して競合を防いでいる.ただ, <tt class="docutils literal">synchronized</tt> は重いので,単に <tt class="docutils literal">synchronized</tt> で初期化するわけではなく,まず単に初期化されているかを確認し,されていなければもう一度 <tt class="docutils literal">synchronized</tt> で確認を行う test and test-and-set みたいなことをしている.最終的にはラムダリフティングとラムダ除去によって,両方 final method として外に出されるっぽい.まあただこのコードならある程度 JVM で出されるコードは予想がつく.実際にコードを見てみる:</p>
<pre class="literal-block">
$ javap -p -v -c 'LazyVal$.class'
...
private static final int v$lzycompute$1(scala.runtime.LazyInt, int);
descriptor: (Lscala/runtime/LazyInt;I)I
flags: ACC_PRIVATE, ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC
Code:
stack=3, locals=4, args_size=2
0: aload_0
1: dup
2: astore_2
3: monitorenter
4: aload_0
5: invokevirtual #33 // Method scala/runtime/LazyInt.initialized:()Z
8: ifeq 18
11: aload_0
12: invokevirtual #37 // Method scala/runtime/LazyInt.value:()I
15: goto 25
18: aload_0
19: iload_1
20: iconst_1
21: iadd
22: invokevirtual #40 // Method scala/runtime/LazyInt.initialize:(I)I
25: istore_3
26: aload_2
27: monitorexit
28: iload_3
29: goto 35
32: aload_2
33: monitorexit
34: athrow
35: ireturn
...
public int func(int);
descriptor: (I)I
flags: ACC_PUBLIC
Code:
stack=2, locals=3, args_size=2
0: new #17 // class scala/runtime/LazyInt
3: dup
4: invokespecial #18 // Method scala/runtime/LazyInt."<init>":()V
7: astore_2
8: aload_2
9: iload_1
10: invokestatic #22 // Method v$1:(Lscala/runtime/LazyInt;I)I
13: iconst_2
14: iadd
15: ireturn
...
</pre>
<p><tt class="docutils literal">v$1</tt> メソッドについては省略した.気になる人は実際に見てくれって感じ. <tt class="docutils literal">func</tt> の中身はほぼそのままって感じだ.問題は, <tt class="docutils literal">v$lzycompute$1</tt> で,なんか色々しとる.とりあえず, <tt class="docutils literal">monitorenter</tt> / <tt class="docutils literal">monitorexit</tt> が <tt class="docutils literal">synchronized</tt> に対応するっぽい.で,これらはロック機構を提供するわけだけど計算中に例外が発生することもあるので,例外が起きた場合にちゃんと <tt class="docutils literal">monitorexit</tt> を走らせないとデッドロック状態になってしまう可能性があるため,そこらへんを解決するコードも入ってるのかな?</p>
<p>さて, <tt class="docutils literal">lazy val</tt> の中身を見たところで,パフォーマンス上気になるのは,以下の 3 点だ:</p>
<ul class="simple">
<li><tt class="docutils literal">LazyInt</tt> を介するため Boxing が挟まる</li>
<li><tt class="docutils literal">monitorenter</tt> / <tt class="docutils literal">monitorexit</tt> により,ロック処理が挟まる</li>
<li><tt class="docutils literal">monitorenter</tt> を挟む際の,例外対処の処理が挟まる</li>
</ul>
<p>このうちどれが大きな問題となるんだろう? とりあえず,まず大雑把に試してみる:</p>
<pre class="literal-block">
$ cat src/LazyValBenchmark.scala
object LazyValBenchmark {
def main(args: Array[String]) {
createLazyVal(10)
createVal(10)
refLazyVal(10)
refVal(10)
println("Warmup end")
{
val start = System.nanoTime();
val r = createVal(0)
val end = System.nanoTime()
println((end - start) + ":" + r)
}
{
val start = System.nanoTime();
val r = createLazyVal(0)
val end = System.nanoTime()
println((end - start) + ":" + r)
}
{
val start = System.nanoTime();
val r = refLazyVal(0)
val end = System.nanoTime()
println((end - start) + ":" + r)
}
{
val start = System.nanoTime();
val r = refVal(0)
val end = System.nanoTime()
println((end - start) + ":" + r)
}
}
val n1 = 1000000000
def createLazyVal(i0: Int): Int = {
var r = 0
while (r < n1) {
lazy val i = i0 + 1
r += i
}
r
}
def createVal(i0: Int): Int = {
var r = 0
while (r < n1) {
val i = i0 + 1
r += i
}
r
}
val n2 = n1
def refLazyVal(i0: Int): Int = {
lazy val i = i0 + 1
var r = 0
while (r < n2) {
r += i
}
r
}
def refVal(i0: Int): Int = {
val i = i0 + 1
var r = 0
while (r < n2) {
r += i
}
r
}
}
$ scalac src/LazyValBenchmark.scala
$ scala LazyValBenchmark
Warmup end
631499976:1000000000
6602310567:1000000000
792000315:1000000000
316664620:1000000000
$ scala LazyValBenchmark
Warmup end
635872302:1000000000
6604901477:1000000000
793790967:1000000000
316887105:1000000000
$ scala LazyValBenchmark
Warmup end
635827311:1000000000
6620801173:1000000000
795464679:1000000000
326651550:1000000000
</pre>
<p>だいぶ飽きてきたので, <tt class="docutils literal">System.nanoTime</tt> 使って適当に済ませてる.よいこは真似しちゃダメだぞっ.結果はまず, <tt class="docutils literal">lazy val</tt> を単に作って参照するだけで,普通の <tt class="docutils literal">val</tt> より 10 倍差ぐらい付いてる.また参照するだけでも 2.6 倍差ぐらい.ただ, <tt class="docutils literal">while</tt> ループとかカウンタとかの固定処理も入っていて結構ガバガバベンチマークではあるので,その結果でこの差ということはかなり性能差がありそう.</p>
<p><tt class="docutils literal">refLazyVal</tt> と <tt class="docutils literal">refVal</tt> の差は,大体 Boxing の差と言えるだろうから, <tt class="docutils literal">Int</tt> 以外で試すともうちょっと結果が変わってくるのかもしれない.疲れたので,今日はそこまでの調査は諦め.まあ, <tt class="docutils literal">Int</tt> そのままだと, <tt class="docutils literal">iload</tt> / <tt class="docutils literal">istore</tt> 命令が使えるのに比べ, <tt class="docutils literal">lazy val</tt> は保存してる値を <tt class="docutils literal">v</tt> 関数と <tt class="docutils literal">value</tt> メソッドを <tt class="docutils literal">invoke</tt> して取りに行かなきゃいけないので差が付くのは仕方ない感がある.ただ, <tt class="docutils literal">lazy val</tt> を何回も参照するなら一旦結果を <tt class="docutils literal">val</tt> に入れた方がいいかもしれないと思うぐらいの差はありそう.</p>
<p><tt class="docutils literal">createLazyVal</tt> と <tt class="docutils literal">createVal</tt> の差に <tt class="docutils literal">refLazyVal</tt> と <tt class="docutils literal">refVal</tt> の差を考慮して考えても,作成と初期化のコストはかなり重いっぽい.作成か初期化どちらが重いか,どちらも重いのかはもう疲れたのでいつかやれたら計ってみたいけど,多分 <tt class="docutils literal">synchronized</tt> が大きく効いてるんだろう.これってスレッドセーフじゃなくていいから,もうちょっと速い <tt class="docutils literal">lazy val</tt> を使いたいみたいな需要はないんだろうか? ガバガバベンチの結果をもとにすれば, <tt class="docutils literal">lazy val</tt> 使うより変数複数管理する方が軽そうだけど.</p>
</div>
<div class="section" id="auto-id-12">
<h2>まとめ<a class="headerlink" href="#auto-id-12" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Scala のコード生成について,今までちゃんと見たことはなかったので,色々試した結果聞いてた噂と同じところ,違うところが知れて良かった.</p>
<p>普段 Haskell 使いの身としては, Haskell は最適化をゴリゴリやるので Scala はあんまり最適化しない印象を受けた.リフレクションのためとかなのかな.後, <tt class="docutils literal"><span class="pre">-Ybrowse</span></tt> 便利. GUI が Java 上だとプラットフォーム関係なしに書けるの,こういう時にも効いてくるんすね.</p>
<p>ちょっと力尽きた感あるので,また時間あったら色々調べてみたいですね</p>
<table class="docutils footnote" frame="void" id="how-to-install-scalac" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><tt class="docutils literal">sbt</tt> で <tt class="docutils literal">scalac</tt> 入れてくれないっぽいので, <tt class="docutils literal">scalac</tt> コマンドを使いたかったら Scala コンパイラを別途に入れる必要があるっぽい.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="why-java-dont-have-tco" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[2]</a></td><td>理由はよく分からない. <a class="reference external" href="https://softwareengineering.stackexchange.com/a/272086">https://softwareengineering.stackexchange.com/a/272086</a> を読む限りでは,正直特に理由はなくて歴史的事情感がある.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="i-knew-it-recently" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-9">[3]</a></td><td>という話を最近知った.それまでこんなテクニック,実際使われてるんかと思ってた.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="non-local-return-control-definition" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-10">[4]</a></td><td><a class="reference external" href="https://github.com/scala/scala/blob/v2.12.8/src/library/scala/runtime/NonLocalReturnControl.scala">https://github.com/scala/scala/blob/v2.12.8/src/library/scala/runtime/NonLocalReturnControl.scala</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="invokedynamic-is-in-java7-yet" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-11">[5]</a></td><td>一応 Java7 から存在してはいたらしいけど,本格的に使われ始めたのは Java8 から</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/scala-compile-inside.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/scala-compile-inside.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>MathML にバイバイして, KaTeX に移行した2019-04-21T17:33:08+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-21:/blog/posts/2019/04/bye-mathml-hello-katex/<p>以前ブログで数式環境を, MathML と MathJax で導入した.ただ色々敗北したので KaTeX を使うことにした.その備忘録.</p>
<div class="section" id="mathml">
<h2>MathML に敗北した<a class="headerlink" href="#mathml" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>正確には, MathML は悪 …</p></div><p>以前ブログで数式環境を, MathML と MathJax で導入した.ただ色々敗北したので KaTeX を使うことにした.その備忘録.</p>
<div class="section" id="mathml">
<h2>MathML に敗北した<a class="headerlink" href="#mathml" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>正確には, MathML は悪くないんだが,現状の MathML + MathJax 環境は色々辛いものがあった.</p>
<ul class="simple">
<li><tt class="docutils literal">\mathit</tt> や <tt class="docutils literal">\mathrel</tt> などの基本的なコマンドに対応していない.</li>
<li>MathJax のレンダリングが遅い.</li>
<li>MathJax がでかい.</li>
</ul>
<p>みたいな感じで,もうちょっとなんとかしたかった.基本的なコマンドに対応していない件は, <tt class="docutils literal">docutils</tt> のデフォルトトランスパイラを使っているのが悪いだろうと思って, <tt class="docutils literal">latexml</tt> を試してみたんだが,こちらは <tt class="docutils literal">\mathbb</tt> に対応していなかったり.そもそも,デフォルトの MathML の段階でフォントの制約がある以上,コマンドはかなり限られてくる.そこら辺のつらみが増した結果, MathML は諦めることにした. MathML を諦めるなら,特に MathJax にこだわる必要もないので, MathJax ともおさらばすることにした.</p>
</div>
<div class="section" id="katex">
<h2>KaTeX の導入<a class="headerlink" href="#katex" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>結局 <tt class="docutils literal">docutils</tt> には生の LaTeX ソースを吐き出させて, KaTeX でレンダリングする感じに落ち着いた. <tt class="docutils literal">docutils</tt> に LaTeX ソースそのままを吐き出させるには, <tt class="docutils literal">pelicanconf.py</tt> で以下のように書けばいい:</p>
<pre class="literal-block">
DOCUTILS_SETTINGS = {
...,
'math_output': 'LaTeX',
}
</pre>
<p>後は, KaTeX をインストールしてレンダリングスクリプトを書いていく:</p>
<pre class="literal-block">
npm i -S katex
</pre>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span>
<span class="normal">29</span>
<span class="normal">30</span>
<span class="normal">31</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">import</span><span class="w"> </span><span class="nx">KaTeX</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">'katex'</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="s1">'katex/dist/katex.min.css'</span><span class="p">;</span>
<span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">renderMathBlock</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="s2">"article.single pre.math"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">ne</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'div'</span><span class="p">);</span>
<span class="w"> </span><span class="nx">ne</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'class'</span><span class="p">,</span><span class="w"> </span><span class="s1">'math block'</span><span class="p">);</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">mathText</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">textContent</span><span class="p">;</span>
<span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">replaceChild</span><span class="p">(</span><span class="nx">ne</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="p">);</span>
<span class="w"> </span><span class="nx">KaTeX</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="nx">mathText</span><span class="p">,</span><span class="w"> </span><span class="nx">ne</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="s2">"article.single tt.math"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">try</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">ne</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'span'</span><span class="p">);</span>
<span class="w"> </span><span class="nx">ne</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'class'</span><span class="p">,</span><span class="w"> </span><span class="s1">'math inline'</span><span class="p">);</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">mathText</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">textContent</span><span class="p">;</span>
<span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">replaceChild</span><span class="p">(</span><span class="nx">ne</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="p">);</span>
<span class="w"> </span><span class="nx">KaTeX</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="nx">mathText</span><span class="p">,</span><span class="w"> </span><span class="nx">ne</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">catch</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>reStructuredText が対応している数式モードは,ディレクティブとロールの 2 種類あり,ディレクティブは <tt class="docutils literal">pre.math</tt> ,ロールは <tt class="docutils literal">tt.math</tt> の中身に LaTeX ソースを埋め込むので,それを KaTeX でレンダリングするだけ.後は, Webpack で CSS ロードとフォントロードの仕組みを導入してやるだけで良い.</p>
</div>
<div class="section" id="postcss">
<h2>PostCSS の導入<a class="headerlink" href="#postcss" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>KaTeX の為に CSS ローダを追加するついでに, PostCSS を導入することにした.まず, KaTeX のための Alias を追加する:</p>
<pre class="literal-block">
resolve: {
alias: {
...,
katex$: 'katex/dist/katex.mjs',
katex: 'katex',
}
},
</pre>
<p>それから, CSS とファイルローダを追加する.CSS を JavaScript と分離するため, <tt class="docutils literal"><span class="pre">mini-css-extract-plugin</span></tt> を使っている:</p>
<pre class="literal-block">
module: {
rules: [
{
test: /\.(scss|css)$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
plugins: function () {
return [
require('cssnano')({
preset: ['default', {
mergeRules: false,
}]
}),
require('precss'),
require('autoprefixer')
];
}
}
},
]
},
{
test: /\.(ttf|woff2?)$/,
use: [
{
loader: 'file-loader'
},
]
}
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css'
})
],
</pre>
<p>PostCSS の cssnano で mergeRules を無効にしているのは,マージアルゴリズムがバグって <a class="footnote-reference" href="#cssnano-mergerules-bug" id="auto-id-1">[1]</a> ツールチップのために指定した CSS のプロパティが消えたため.後は,既存の CSS ファイルを PostCSS で書き直した.これで適当にベンダープレフィックスとかも入れてくれる.</p>
<p>それから,数式のスタイルも少しいじった:</p>
<pre class="literal-block">
article.single {
div.math.block {
overflow-x: auto;
overflow-y: hidden;
text-align: center;
}
}
</pre>
<p>overflow 時の設定を加えて,センタリングされるようにした. <tt class="docutils literal"><span class="pre">overflow-y:</span> hidden</tt> を加えてるのは,なぜか KaTeX の方で数式の下に変な余白が生まれ,謎のスクロールが発生していたため.後はエントリーポイントの JavaScript に CSS をインポートするよう記述を加えるだけ.</p>
</div>
<div class="section" id="auto-id-2">
<h2>まとめ<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>これで JavaScript が必須のブログになってしまった (LaTeX の脳内レンダリングできる人なら読めるが) .ま,今の時代 JavaScript 無効にしてる人なんておらんやろ.</p>
<p>PostCSS も導入できたし,大分ブログの管理状況は人権があるものになったんじゃないかな.MathML が使えなくなったのはちょっと残念だけど.</p>
<table class="docutils footnote" frame="void" id="cssnano-mergerules-bug" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td><a class="reference external" href="https://github.com/cssnano/cssnano/issues/701">https://github.com/cssnano/cssnano/issues/701</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/bye-mathml-hello-katex.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/bye-mathml-hello-katex.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>STG Version 2.5 の動作2019-04-19T11:08:35+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-19:/blog/posts/2019/04/haskell-old-stg-syntax/<p>先日 STG の動作について説明する機会があったんだが,ちゃんと説明できなかった.で,ちょっとこれじゃまずいって思 …</p><p>先日 STG の動作について説明する機会があったんだが,ちゃんと説明できなかった.で,ちょっとこれじゃまずいって思って,色々読み直してる.で,いざっていう時のためにまとめとくかみたいな気分になっており,この記事が錬成された.なお,今の GHC の STG では色々変わってるので通用しないとこも多い.そこは注意.</p>
<div class="section" id="stg">
<h2>この記事での STG について<a class="headerlink" href="#stg" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>この記事での STG は, Spineless Tagless G-machine Version 2.5 の事を指している.内容としては,SPJ が出した 1992年 JFP の</p>
<blockquote>
Jones, S. L. P. (1992). Implementing lazy functional languages on stock hardware: the Spineless Tagless G-machine. Journal of Functional Programming, 2(02), 127–202. <a class="reference external" href="https://doi.org/10.1017/S0956796800000319">https://doi.org/10.1017/S0956796800000319</a></blockquote>
<p>を基にしている. Microsoft Research のページから PDF は見れる: <a class="reference external" href="https://www.microsoft.com/en-us/research/publication/implementing-lazy-functional-languages-on-stock-hardware-the-spineless-tagless-g-machine/">https://www.microsoft.com/en-us/research/publication/implementing-lazy-functional-languages-on-stock-hardware-the-spineless-tagless-g-machine/</a></p>
<p>STG の名前は,</p>
<ol class="arabic simple">
<li>G-machine (graph reduction machine): Johnsson, T. (1987). Compiling Lazy Functional Languages: An introduction. PhD thesis, Chalmers University.</li>
<li>Spineless G-machine: Burn, G. L., Peyton Jones, S. L., & Robson, J. D. (1988). The spineless G-machine. In Proceedings of the 1988 ACM conference on LISP and functional programming - LFP ’88 (pp. 244–258). New York, New York, USA: ACM Press. <a class="reference external" href="https://doi.org/10.1145/62678.62717">https://doi.org/10.1145/62678.62717</a></li>
<li>Spineless Tagless G-machine</li>
</ol>
<p>みたいな変遷をたどっている.今となっては, pointer tagging が採用されたため tagless というワードは通用しなくなったり,実行モデルが変わったりという感じだが <a class="footnote-reference" href="#spineless-is-still" id="auto-id-1">[1]</a> ,今でも STG という名前が使われている.まあ大枠は G-machine の拡張なので,いけるでしょ <a class="footnote-reference" href="#shared-term-graph" id="auto-id-2">[2]</a>.</p>
<p>てなわけで, STG Version 2.5 について見ていこうと思う.お気持ちの部分はかなりすっ飛ばすので,もっと詳しく知りたいとかちゃんとした情報が知りたい人は上の論文を読んでくれって感じ.今の STG に受け継がれてるとこは多いというか,多分上のやつ読まないとその後の話の大部分分からない気がするので,読んでみるのはオススメ.</p>
</div>
<div class="section" id="auto-id-3">
<h2>STG の概要<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>GHC では,</p>
<ol class="arabic simple">
<li>Haskell: これはみなさんご存知の通りのやつ</li>
<li>Core: 複雑な構文 (型クラスとかも) の脱糖,型の明記などが行われたやつ</li>
<li>STG: 抽象機械,大体の実行時の動作を表す表現</li>
<li>C--: C のサブセット</li>
<li>バックエンド: LLVM / アセンブリなど</li>
</ol>
<p>みたいなフローでコンパイルが行われていて,大体は Core-to-Core で最適化が行われて, STG として吐き出された後操作的意味論に合うように C-- が吐き出される,いわば低レベル動作から離れた位置の高尚な言語から,低レベル動作がある程度考慮された言語への橋渡しみたいな位置にいるのが, STG になる.</p>
<p>Haskell は <tt class="docutils literal">case</tt> であっても評価が起きなかったり,式中でヒープ割り当てが発生して位置を特定しにくいとか,正直コードの動作が追えたものじゃない <a class="footnote-reference" href="#haskell-optimizing-community" id="auto-id-4">[3]</a> . STG は Haskell の文法に寄せながらも動作が分かりやすいようになっている型無しの言語で,主要な構文とその操作的意味論が大体以下のように対応する:</p>
<table border="1" class="docutils">
<colgroup>
<col width="58%"/>
<col width="42%"/>
</colgroup>
<thead valign="bottom">
<tr><th class="head">構文</th>
<th class="head">操作的意味論</th>
</tr>
</thead>
<tbody valign="top">
<tr><td>関数適用</td>
<td>末尾呼び出し</td>
</tr>
<tr><td>let 式</td>
<td>ヒープ割り当て</td>
</tr>
<tr><td>case 式</td>
<td>評価</td>
</tr>
<tr><td>コンストラクタへの適用</td>
<td>継続への復帰</td>
</tr>
</tbody>
</table>
<p>コンストラクタへの適用が継続への復帰に対応するというのは分かる人には分かると思うけど,分からない人は何を言ってるか分からないと思う.これについては後述するので,今は気にしなくていい.この機能が tagless の由来だったりする.後の対応関係はいいと思う.通常の Haskell だとここまでうまく対応しないけど, STG は対応させるため構文に色々制約を設けてる.</p>
</div>
<div class="section" id="auto-id-5">
<h2>STG の構文<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>実際の構文は以下の感じ:</p>
<dl class="docutils">
<dt>基本要素</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>v</mi><mi>a</mi><mi>r</mi><mi>s</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><mo stretchy="false">{</mo><msub><mrow><mi>v</mi><mi>a</mi><mi>r</mi></mrow><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mrow><mi>v</mi><mi>a</mi><mi>r</mi></mrow><mi>n</mi></msub><mo stretchy="false">}</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>≥</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>v</mi><mi>a</mi><mi>r</mi></mrow><mo>∈</mo><mrow><mi>V</mi><mi>A</mi><mi>R</mi></mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>V</mi><mi>A</mi><mi>R</mi></mrow></mstyle><mtext> は変数集合</mtext></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>a</mi><mi>t</mi><mi>o</mi><mi>m</mi><mi>s</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><mo stretchy="false">{</mo><msub><mrow><mi>a</mi><mi>t</mi><mi>o</mi><mi>m</mi></mrow><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mrow><mi>a</mi><mi>t</mi><mi>o</mi><mi>m</mi></mrow><mi>n</mi></msub><mo stretchy="false">}</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>≥</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>a</mi><mi>t</mi><mi>o</mi><mi>m</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><mrow><mi>v</mi><mi>a</mi><mi>r</mi></mrow><mo>∣</mo><mrow><mi>l</mi><mi>i</mi><mi>t</mi><mi>e</mi><mi>r</mi><mi>a</mi><mi>l</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>l</mi><mi>i</mi><mi>t</mi><mi>e</mi><mi>r</mi><mi>a</mi><mi>l</mi></mrow><mo>∈</mo><mrow><mi>L</mi><mi>I</mi><mi>T</mi></mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>L</mi><mi>I</mi><mi>T</mi></mrow></mstyle><mtext> はリテラル集合</mtext></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>p</mi><mi>r</mi><mi>i</mi><mi>m</mi></mrow><mo>∈</mo><mrow><mi>P</mi><mi>R</mi><mi>I</mi><mi>M</mi></mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>P</mi><mi>R</mi><mi>I</mi><mi>M</mi></mrow></mstyle><mtext> はプリミティブ演算子の集合</mtext></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>c</mi><mi>o</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>r</mi></mrow><mo>∈</mo><mrow><mi>C</mi><mi>O</mi><mi>N</mi></mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>C</mi><mi>O</mi><mi>N</mi></mrow></mstyle><mtext> はコンストラクタの集合</mtext></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{ll}
\mathit{vars} \mathrel{::=} \{\mathit{var}_1, \ldots, \mathit{var}_n\} & (n \geq 0) \\
\mathit{var} \in \mathit{VAR} & (\text{\(\mathit{VAR}\) は変数集合}) \\
\\
\mathit{atoms} \mathrel{::=} \{\mathit{atom}_1, \ldots, \mathit{atom}_n\} & (n \geq 0) \\
\mathit{atom} \mathrel{::=} \mathit{var} \mid \mathit{literal} \\
\\
\mathit{literal} \in \mathit{LIT} & (\text{\(\mathit{LIT}\) はリテラル集合}) \\
\mathit{prim} \in \mathit{PRIM} &(\text{\(\mathit{PRIM}\) はプリミティブ演算子の集合}) \\
\mathit{constr} \in \mathit{CON} &(\text{\(\mathit{CON}\) はコンストラクタの集合})
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:10.8em;vertical-align:-5.15em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.65em;"><span style="top:-7.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vars</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mord"><span class="mord"><span class="mord mathit">var</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">var</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span><span style="top:-6.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">var</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">VAR</span></span></span></span><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">atoms</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mord"><span class="mord"><span class="mord mathit">atom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">atom</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">atom</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">var</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">literal</span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">literal</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">LIT</span></span></span></span><span style="top:0.59em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">prim</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">PRIM</span></span></span></span><span style="top:1.79em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">constr</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">CON</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:5.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.65em;"><span style="top:-7.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-6.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathit">VAR</span></span><span class="mord"> </span><span class="mord cjk_fallback">は変数集合</span></span><span class="mclose">)</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathit">LIT</span></span><span class="mord"> </span><span class="mord cjk_fallback">はリテラル集合</span></span><span class="mclose">)</span></span></span><span style="top:0.59em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathit">PRIM</span></span><span class="mord"> </span><span class="mord cjk_fallback">はプリミティブ演算子の集合</span></span><span class="mclose">)</span></span></span><span style="top:1.79em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathit">CON</span></span><span class="mord"> </span><span class="mord cjk_fallback">はコンストラクタの集合</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:5.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">基本要素は以上のやつになる.リテラルは, unboxed な値を想定してて, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>L</mi><mi>I</mi><mi>T</mi></mrow><mo>=</mo><mo stretchy="false">{</mo><mtext mathvariant="monospace">0#</mtext><mo separator="true">,</mo><mtext mathvariant="monospace">1#</mtext><mo separator="true">,</mo><mo>…</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\mathit{LIT} = \{\text{\tt 0\#}, \text{\tt 1\#}, \ldots\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathit">LIT</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord text"><span class="mord"><span class="mord mathtt">0#</span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">1#</span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mclose">}</span></span></span></span></span> みたいなのが書ける.また,プリミティブ演算子も同じく, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi>P</mi><mi>R</mi><mi>I</mi><mi>M</mi></mrow><mo>=</mo><mo stretchy="false">{</mo><mtext mathvariant="monospace">+#</mtext><mo separator="true">,</mo><mtext mathvariant="monospace">*#</mtext><mo separator="true">,</mo><mo>…</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">\mathit{PRIM} = \{\text{\tt +\#}, \text{\tt *\#}, \ldots\}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathit">PRIM</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord text"><span class="mord"><span class="mord mathtt">+#</span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">*#</span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mclose">}</span></span></span></span></span> みたいなのが書ける.変数とコンストラクタは Haskell と同じ習慣に従ってて,アルファベットの場合変数は先頭小文字,コンストラクタは大文字で始まる.ただ,ここら辺は本質情報じゃなくてもちろん取り換え可能.</p>
</dd>
<dt>ラムダ式</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>l</mi><mi>f</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><msub><mrow><mi>v</mi><mi>a</mi><mi>r</mi><mi>s</mi></mrow><mi>f</mi></msub><mo><mtext mathvariant="monospace">\</mtext><mi>π</mi></mo><msub><mrow><mi>v</mi><mi>a</mi><mi>r</mi><mi>s</mi></mrow><mi>a</mi></msub><mo><mtext mathvariant="monospace">-></mtext></mo><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>π</mi><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><mi mathvariant="monospace">u</mi><mo>∣</mo><mi mathvariant="monospace">n</mi></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{l}
\mathit{lf} \mathrel{::=} \mathit{vars}_f \mathrel{\text{\tt \textbackslash} \pi} \mathit{vars}_a \mathrel{\text{\tt ->}} \mathit{expr} \\
\\
\pi \mathrel{::=} \mathtt{u} \mid \mathtt{n}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">lf</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vars</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord mathnormal" style="margin-right:0.03588em;">π</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vars</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">expr</span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathtt">u</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathtt">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>この式はクロージャを表し, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi>v</mi><mi>a</mi><mi>r</mi><mi>s</mi></mrow><mi>f</mi></msub></mrow><annotation encoding="application/x-tex">\mathit{vars}_f</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vars</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span> が自由変数, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mrow><mi>v</mi><mi>a</mi><mi>r</mi><mi>s</mi></mrow><mi>a</mi></msub></mrow><annotation encoding="application/x-tex">\mathit{vars}_a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vars</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> がクロージャの引数になる. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>π</mi></mrow><annotation encoding="application/x-tex">\pi</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">π</span></span></span></span></span> は更新フラグで,更新できるかどうかを表す. <tt class="docutils literal">u</tt> が更新可能, <tt class="docutils literal">n</tt> が更新不要を表し, <tt class="docutils literal">u</tt> の場合要はサンクを表す.後更新フラグは以下のように決める:</p>
<ul class="simple">
<li>以下に該当するものは <tt class="docutils literal">n</tt> をセットする:<ul>
<li>引数が 1 以上のクロージャ: <tt class="docutils literal">{f} \n {x} <span class="pre">-></span> case 1# of v <span class="pre">-></span> f {v, x}</tt></li>
<li>中身がコンストラクタ適用となっているクロージャ: <tt class="docutils literal">{x, l} \n {} <span class="pre">-></span> Cons {x, l}</tt></li>
<li>(オプショナル) 部分適用</li>
<li>(オプショナル) 一度しか使われないことが分かっているクロージャ</li>
</ul>
</li>
<li>それ以外の場合は, <tt class="docutils literal">u</tt> をセットする.</li>
</ul>
<p>これは本質的な制約じゃなくて,更新フラグを全部 <tt class="docutils literal">u</tt> から始めてもいい.ただ, STG は抽象機械を想定してるので,最初から更新不要と分かってるとこには <tt class="docutils literal">n</tt> を書いておいた方が都合がいい.なので,後ろに載せた意味論はこの制約を守ってる前提で書かれてる.なお,オプショナルになっている制約は,実はやらなくても意味論は機能する.特に,クロージャが一度しか使われないかを完全に解析することは困難なので,一度しか使われないクロージャでも <tt class="docutils literal">u</tt> がセットされることはある.</p>
<p class="last"><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><annotation encoding="application/x-tex">\mathit{expr}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathit">expr</span></span></span></span></span></span> はまだ説明してないが主要な構文と <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi>t</mi><mi>o</mi><mi>m</mi></mrow><annotation encoding="application/x-tex">atom</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">o</span><span class="mord mathnormal">m</span></span></span></span></span> ぐらいが書ける.この後に書いてあるので,気になったら適当にフライングしてくれ.</p>
</dd>
<dt>束縛</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>p</mi><mi>r</mi><mi>o</mi><mi>g</mi><mi>r</mi><mi>a</mi><mi>m</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><mrow><mi>b</mi><mi>i</mi><mi>n</mi><mi>d</mi><mi>s</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>b</mi><mi>i</mi><mi>n</mi><mi>d</mi><mi>s</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><msub><mrow><mi>v</mi><mi>a</mi><mi>r</mi></mrow><mn>1</mn></msub><mo>=</mo><msub><mrow><mi>l</mi><mi>f</mi></mrow><mn>1</mn></msub><mo lspace="0em" rspace="0.17em" separator="true">;</mo><mo>⋯</mo><mo lspace="0em" rspace="0.17em" separator="true">;</mo><msub><mrow><mi>v</mi><mi>a</mi><mi>r</mi></mrow><mi>n</mi></msub><mo>=</mo><msub><mrow><mi>l</mi><mi>f</mi></mrow><mi>n</mi></msub></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>≥</mo><mn>1</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{ll}
\mathit{program} \mathrel{::=} \mathit{binds} \\
\\
\mathit{binds} \mathrel{::=} \mathit{var}_1 = \mathit{lf}_1 \mathpunct{;} \cdots \mathpunct{;} \mathit{var}_n = \mathit{lf}_n &(n \geq 1)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">program</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">binds</span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">binds</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">var</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">lf</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mpunct"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">var</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">lf</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0573em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-0.35em;"><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">束縛は, let 式で使われる他, STG のプログラムも束縛で表現される. Haskell と違って, STG では束縛でパターンマッチとかできないし,クロージャしか束縛できない.なお, STG にはもう 1 つ束縛の仕方があって, case 式を使えば評価結果を束縛できる.なので,この束縛はヒープ割り当て用, case は式の評価値束縛用みたいな感じ.束縛はクロージャしかできないので,プリミティブな値を束縛したい時とかも case を使う必要がある.</p>
</dd>
<dt>let (rec) 式</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>l</mi><mi>e</mi><mi>t</mi><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">let</mtext><mtext> </mtext><mrow><mi>b</mi><mi>i</mi><mi>n</mi><mi>d</mi><mi>s</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">in</mtext><mtext> </mtext><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">letrec</mtext><mtext> </mtext><mrow><mi>b</mi><mi>i</mi><mi>n</mi><mi>d</mi><mi>s</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">in</mtext><mtext> </mtext><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rl}
\mathit{letexpr}
\mathrel{::=}& \text{\tt let} \,\mathit{binds}\,\text{\tt in}\, \mathit{expr} \\
\mid& \text{\tt letrec} \,\mathit{binds}\,\text{\tt in}\, \mathit{expr}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">letexpr</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">let</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">binds</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">expr</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">letrec</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">binds</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">expr</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">まあこれはいいでしょ. Haskell では let 式中で再帰的な変数が書け,コンパイル時に静的に再帰的かどうか解析されるが, STG では再帰的に書けるかどうかが構文レベルで区別されている.もちろん, let は素直に実装できるが, letrec は循環参照を含む場合があるのでちょっと工夫が必要.後,今回は説明しないが letrec は無限ループチェックのためブラックホールという機能が搭載されるので,重いみたいなんもある.</p>
</dd>
<dt>case 式</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>c</mi><mi>a</mi><mi>s</mi><mi>e</mi><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><mtext mathvariant="monospace">case</mtext><mtext> </mtext><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">of</mtext><mtext> </mtext><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mtable columnalign="right left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mrow><mi>a</mi><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mn>1</mn></msub><mo lspace="0em" rspace="0.17em" separator="true">;</mo><mo>⋯</mo><mo lspace="0em" rspace="0.17em" separator="true">;</mo><msub><mrow><mi>a</mi><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mi>n</mi></msub><mo lspace="0em" rspace="0.17em" separator="true">;</mo><mrow><mi>d</mi><mi>e</mi><mi>f</mi><mi>a</mi><mi>u</mi><mi>l</mi><mi>t</mi></mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>≥</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mrow><mi>p</mi><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mn>1</mn></msub><mo lspace="0em" rspace="0.17em" separator="true">;</mo><mo>⋯</mo><mo lspace="0em" rspace="0.17em" separator="true">;</mo><msub><mrow><mi>p</mi><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mi>n</mi></msub><mo lspace="0em" rspace="0.17em" separator="true">;</mo><mrow><mi>d</mi><mi>e</mi><mi>f</mi><mi>a</mi><mi>u</mi><mi>l</mi><mi>t</mi></mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>≥</mo><mn>0</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mtable columnalign="right left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>a</mi><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>c</mi><mi>o</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>r</mi></mrow><mtext> </mtext><mrow><mi>v</mi><mi>a</mi><mi>r</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">-></mtext></mo><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>p</mi><mi>a</mi><mi>l</mi><mi>t</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>l</mi><mi>i</mi><mi>t</mi><mi>e</mi><mi>r</mi><mi>a</mi><mi>l</mi></mrow><mo><mtext mathvariant="monospace">-></mtext></mo><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>d</mi><mi>e</mi><mi>f</mi><mi>a</mi><mi>u</mi><mi>l</mi><mi>t</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>v</mi><mi>a</mi><mi>r</mi></mrow><mo><mtext mathvariant="monospace">-></mtext></mo><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">default</mtext><mo><mtext mathvariant="monospace">-></mtext></mo><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow></mrow></mstyle></mtd></mtr></mtable></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{l}
\mathit{caseexpr} \mathrel{::=} \text{\tt case} \, \mathit{expr} \, \text{\tt of} \, \mathit{alts} \\
\\
\begin{array}{rll}
\mathit{alts}
\mathrel{::=}& \mathit{aalt}_1 \mathpunct{;} \cdots \mathpunct{;} \mathit{aalt}_n \mathpunct{;} \mathit{default} &(n \geq 0) \\
\mid& \mathit{palt}_1 \mathpunct{;} \cdots \mathpunct{;} \mathit{palt}_n \mathpunct{;} \mathit{default} &(n \geq 0)
\end{array} \\
\\
\begin{array}{rl}
\mathit{aalt} \mathrel{::=}& \mathit{constr}\,\mathit{vars} \mathrel{\text{\tt ->}} \mathit{expr} \\
\mathit{palt} \mathrel{::=}& \mathit{literal} \mathrel{\text{\tt ->}} \mathit{expr} \\
\mathit{default} \mathrel{::=}& \mathit{var} \mathrel{\text{\tt ->}} \mathit{expr} \\
\mid& \text{\tt default} \mathrel{\text{\tt ->}} \mathit{expr}
\end{array}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:10.8em;vertical-align:-5.15em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.65em;"><span style="top:-9.46em;"><span class="pstrut" style="height:4.65em;"></span><span class="mord"><span class="mord"><span class="mord mathit">caseexpr</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">case</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">expr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">of</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">alts</span></span></span></span><span style="top:-8.26em;"><span class="pstrut" style="height:4.65em;"></span><span class="mord"></span></span><span style="top:-6.45em;"><span class="pstrut" style="height:4.65em;"></span><span class="mord"><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">alts</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">aalt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">aalt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">default</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">palt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mpunct"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">palt</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0573em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mpunct"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">default</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span><span style="top:-4.66em;"><span class="pstrut" style="height:4.65em;"></span><span class="mord"></span></span><span style="top:-1.65em;"><span class="pstrut" style="height:4.65em;"></span><span class="mord"><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">aalt</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">palt</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">default</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">constr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vars</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">expr</span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">literal</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">expr</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">var</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">expr</span></span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">default</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">expr</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:5.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">case 式は,まず一層しかパターンマッチできなくて,しかもリテラルかコンストラクタかで分かれてる (これは当たり前といえばそうか). でいずれにもマッチしなかった場合のデフォルトで評価値を捨てるか,束縛するかを選べるみたいな感じ.</p>
</dd>
<dt>関数適用</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="right left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>a</mi><mi>p</mi><mi>p</mi><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>v</mi><mi>a</mi><mi>r</mi></mrow><mtext> </mtext><mrow><mi>a</mi><mi>t</mi><mi>o</mi><mi>m</mi><mi>s</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>c</mi><mi>o</mi><mi>n</mi><mi>s</mi><mi>t</mi><mi>r</mi></mrow><mtext> </mtext><mrow><mi>a</mi><mi>t</mi><mi>o</mi><mi>m</mi><mi>s</mi></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mo lspace="0em" rspace="0em">∣</mo></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>p</mi><mi>r</mi><mi>i</mi><mi>m</mi></mrow><mtext> </mtext><mrow><mi>a</mi><mi>t</mi><mi>o</mi><mi>m</mi><mi>s</mi></mrow></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{rl}
\mathit{appexpr}
\mathrel{::=}& \mathit{var}\, \mathit{atoms} \\
\mid& \mathit{constr}\, \mathit{atoms} \\
\mid& \mathit{prim}\, \mathit{atoms}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">appexpr</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∣</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">var</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">atoms</span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">constr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">atoms</span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">prim</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">atoms</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">関数適用は適用する対象によって色々分かれてる.動作も違ったりするが,それについては後ほど.あともう一つの特徴として, Haskell と違って,引数は必ず事前にヒープ割り当てしてある変数 <a class="footnote-reference" href="#all-variables-were-heap-allocated" id="auto-id-6">[4]</a> かリテラルだけ.</p>
</dd>
<dt>式</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><mo><mo>:</mo><mo>:</mo><mo>=</mo></mo><mrow><mi>l</mi><mi>e</mi><mi>t</mi><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><mo>∣</mo><mrow><mi>c</mi><mi>a</mi><mi>s</mi><mi>e</mi><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><mo>∣</mo><mrow><mi>a</mi><mi>p</mi><mi>p</mi><mi>e</mi><mi>x</mi><mi>p</mi><mi>r</mi></mrow><mo>∣</mo><mrow><mi>l</mi><mi>i</mi><mi>t</mi><mi>e</mi><mi>r</mi><mi>a</mi><mi>l</mi></mrow></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{l}
\mathit{expr}
\mathrel{::=} \mathit{letexpr}
\mid \mathit{caseexpr}
\mid \mathit{appexpr}
\mid \mathit{literal}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1.2em;vertical-align:-0.35em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.85em;"><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathit">expr</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">::=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">letexpr</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">caseexpr</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">appexpr</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">literal</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">式は単純に今まで出てきた主要な式 + リテラルが書ける感じ.これは特にいうことないっすね.</p>
</dd>
</dl>
<p>気持ち的には特に最適化を考慮しなければ, Haskell と STG は以下の感じで対応する <a class="footnote-reference" href="#example-by-paper" id="auto-id-7">[5]</a> .</p>
<p>Haskell:</p>
<pre class="literal-block">
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
</pre>
<p>STG:</p>
<pre class="literal-block">
map = {} \n {f, xs} ->
case xs of
Nil {} -> Nil {}
Cons {y, ys} ->
let fy = {f, y} \u {} -> f {y}
mfys = {f, ys} \u {} -> map {f, ys}
in Cons {fy, mfys}
</pre>
<p><tt class="docutils literal">Nil</tt> と <tt class="docutils literal">Cons</tt> は <tt class="docutils literal">[]</tt> と <tt class="docutils literal">:</tt> に対応する単なるコンストラクタを表す文字列と思ってもらって良い.こいつら自体に特に表現はない.それでどうやってパターンマッチを動作させるのかは,意味論を参照. <tt class="docutils literal">map = \f xs <span class="pre">-></span> case xs of ...</tt> に注意すると,最初の方は良いだろう. <tt class="docutils literal">map</tt> はラムダそのままなので既に WHNF であり,サンクにする要素はないので <tt class="docutils literal">n</tt> (更新不要) が指定される.逆に <tt class="docutils literal">fy</tt> と <tt class="docutils literal">mfys</tt> はサンクになっていて,それぞれクロージャとしてヒープ割り当てが行われる.この割り当ては,適用の際引数が変数かリテラルでないとだめという制約に忠実に従うとこう書くしかなくて, STG は構文レベルで実行動作と対応できるようになっている.</p>
<p>後論文でもう 1 つ例が挙げられていたので,そちらも紹介しておく.</p>
<p>Haskell:</p>
<pre class="literal-block">
map1 :: (a -> b) -> [a] -> [b]
map1 f = mf
where
mf [] = []
mf (x:xs) = f x : mf xs
</pre>
<p>STG:</p>
<pre class="literal-block">
map1 = {} \n {f} ->
letrec
mf = {f, mf} \n {xs} ->
case xs of
Nil {} -> Nil {}
Cons {y, ys} ->
let fy = {f, y} \u {} -> f {y}
mfys = {mf, ys} \u {} -> mf {ys}
in Cons {fy, mfys}
in mf
</pre>
<p>この例は重要な例ではあるんだけど,とりあえずここでは, STG の構文に慣れてもらえれば良い.分かっている人は, STG のクロージャは自由変数と引数両方持てるよと認識してもらえば良い.今回は <tt class="docutils literal">mf</tt> がその例となっている.</p>
</div>
<div class="section" id="auto-id-8">
<h2>STG の意味論<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>STG の意味論は表示的にはクロージャの自由変数とか更新フラグとか全部無視して Haskell と同じ感じの意味を持たせることができる.ただ抽象機械なので重要なのは操作的な方だよねってことで,操作的意味論をまとめておく.</p>
<div class="section" id="auto-id-9">
<h3>準備<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>操作的意味論は,状態機械で定義されていて,遷移は評価ステップになっている.基本的な用語として,</p>
<dl class="docutils">
<dt>アドレス</dt>
<dd>ヒープのアドレス.表現はなんでも良いが,通常の非負整数と思っておいてくれ.</dd>
<dt>値</dt>
<dd><p class="first">以下の 2 種類:</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi></mrow><annotation encoding="application/x-tex">\mathbf{Addr}\,a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span></span></span></span></span> : アドレス</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mi>n</mi></mrow><annotation encoding="application/x-tex">\mathbf{Int}\,n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span> : プリミティブの整数</li>
</ul>
<p class="last">なお,プリミティブな値は増やそうと思えばいくらでも増やせるが,定義を書く上ではめんどいので,整数のみを扱う.</p>
</dd>
</dl>
<p>で使っていくのでよろしく.で,状態機械の状態は以下の要素の組として定義されている:</p>
<dl class="docutils">
<dt>引数スタック ( <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{as}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord"><span class="mord mathit">as</span></span></span></span></span></span> )</dt>
<dd>値の列.関数の引数として使用されるやつらが入ってる.</dd>
<dt>返り値スタック ( <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>r</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{rs}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord"><span class="mord mathit">rs</span></span></span></span></span></span> )</dt>
<dd>継続の列.これが tagless の所以なんだが,返り値スタックが使用されるのは case 式で, case はまず評価が終わった後の分岐 (パターンマッチ) を継続の形で返り値スタックに入れておき,評価値が返り値スタックの分岐から継続を選びそこを実行するみたいな感じになっている.実際の動きは,この後の操作的意味論を見ながら話す.</dd>
<dt>更新スタック ( <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>u</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">\mathit{us}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord"><span class="mord mathit">us</span></span></span></span></span></span> )</dt>
<dd>サンクを評価する際に,現在のスタック情報を退避させておくためのフレームスタックで,退避させた引数スタックと返り値スタック,更新しているクロージャのアドレスの列が入っている.</dd>
<dt>ヒープ ( <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi></mrow><annotation encoding="application/x-tex">h</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span></span></span></span></span> )</dt>
<dd>アドレスとクロージャの対応が入ってる.</dd>
<dt>グローバル環境 ( <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>σ</mi></mrow><annotation encoding="application/x-tex">\sigma</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span></span> )</dt>
<dd>トップレベルで束縛された変数とクロージャのアドレスの対応が入ってる.</dd>
<dt>命令</dt>
<dd><p class="first">以下の 4 種類の命令:</p>
<ul class="simple">
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mi>e</mi><mtext> </mtext><mi>ρ</mi></mrow><annotation encoding="application/x-tex">\mathbf{Eval}\,e\,\rho</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span></span></span></span></span> : STG の式 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> を環境 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ρ</mi></mrow><annotation encoding="application/x-tex">\rho</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span></span></span></span></span> で評価する.</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi></mrow><annotation encoding="application/x-tex">\mathbf{Enter}\,a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span></span></span></span></span> : アドレス <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi></mrow><annotation encoding="application/x-tex">a</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span> にあるクロージャに,引数スタックに積まれてるものを引数として適用する.</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mi>c</mi><mtext> </mtext><mrow><mi>w</mi><mi>s</mi></mrow></mrow><annotation encoding="application/x-tex">\mathbf{ReturnCon}\,c\,\mathit{ws}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ws</span></span></span></span></span></span> : コンストラクタ <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>c</mi></mrow><annotation encoding="application/x-tex">c</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">c</span></span></span></span></span> とその適用された値 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>w</mi><mi>s</mi></mrow><annotation encoding="application/x-tex">ws</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mord mathnormal">s</span></span></span></span></span> から,返り値スタックにある継続を実行する.</li>
<li><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mi>n</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnInt}\,n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnInt</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span> : プリミティブ整数 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span> から,返り値スタックにある継続を実行する.</li>
</ul>
<p class="last">なお, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnInt}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnInt</span></span></span></span></span></span> は <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnCon}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnCon</span></span></span></span></span></span> のプリミティブ向け特殊版と考えれば良い.整数は引数無しのコンストラクタと大体同じ.</p>
</dd>
</dl>
<p>カッコ内に書いてあるのはメタ変数.以降はこの系統のメタ変数を使っていく.それから以下の補助関数を用意しておく:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>v</mi><mi>a</mi><mi>l</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mi>n</mi></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mi>x</mi><mo>=</mo><mi>n</mi></mstyle><mtext> は整数</mtext></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>v</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>ρ</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><mi>v</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>σ</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mtext>otherwise</mtext><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>s</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mo stretchy="false">{</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mi>x</mi><mi>n</mi></msub><mo stretchy="false">}</mo><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">[</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><msub><mi>x</mi><mi>n</mi></msub><mo stretchy="false">)</mo><mo stretchy="false">]</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\mathit{val}(\langle \rho, \sigma\rangle, x) = \left\{\begin{array}{ll}
\mathbf{Int}\,n &(\text{\(x = n\) は整数}) \\
v &(\rho(x) = v) \\
\sigma(x) &(\text{otherwise})
\end{array}\right. \\
\mathit{vals}(\langle \rho, \sigma\rangle, \{x_1, \ldots, x_n\}) =
[\mathit{val}(\langle \rho, \sigma\rangle, x_1), \ldots, \mathit{val}(\langle \rho, \sigma\rangle, x_n)]
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:4.8em;vertical-align:-2.15em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:4.05em;"></span><span class="mord"><span class="mord"><span class="mord mathit">val</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-2.5em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.492em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.016em;width:0.8889em;"><svg height="0.016em" preserveaspectratio="xMinYMin" style="width:0.8889em" viewbox="0 0 888.89 16" width="0.8889em" xmlns="http://www.w3.org/2000/svg"><path d="M384 0 H504 V16 H384z M384 0 H504 V16 H384z"></path></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.016em;width:0.8889em;"><svg height="0.016em" preserveaspectratio="xMinYMin" style="width:0.8889em" viewbox="0 0 888.89 16" width="0.8889em" xmlns="http://www.w3.org/2000/svg"><path d="M384 0 H504 V16 H384z M384 0 H504 V16 H384z"></path></svg></span></span><span style="top:-4.3em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">n</span><span class="mord"> </span><span class="mord cjk_fallback">は整数</span></span><span class="mclose">)</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">ρ</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord text"><span class="mord">otherwise</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-2.26em;"><span class="pstrut" style="height:4.05em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vals</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">})</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathit">val</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">val</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)]</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>この関数はまずローカルスコープで変数を探して,なかったらグローバルスコープで探し,その変数に対応するクロージャのアドレスを返す.では,実際の意味論を見ていく.</p>
</div>
<div class="section" id="auto-id-10">
<h3>初期状態<a class="headerlink" href="#auto-id-10" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>まず, STG のプログラム</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>g</mi><mn>1</mn></msub><mo>=</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">\</mtext><msub><mi>π</mi><mn>1</mn></msub></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mn>1</mn></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi><mi mathvariant="normal">⋮</mi><mpadded height="0em" voffset="0em"><mspace height="1.5em" mathbackground="black" width="0em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>g</mi><mi>n</mi></msub><mo>=</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">\</mtext><msub><mi>π</mi><mi>n</mi></msub></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mi>n</mi></msub></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
g_1 = \mathit{vs}_1 \mathrel{\text{\tt \textbackslash}\pi_1} \mathit{xs}_1 \mathrel{\text{\tt ->}} e_1 \\
\vdots \\
g_n = \mathit{vs}_n \mathrel{\text{\tt \textbackslash}\pi_n} \mathit{xs}_n \mathrel{\text{\tt ->}} e_n
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:4.26em;vertical-align:-1.88em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.38em;"><span style="top:-5.2275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.3675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-2.1675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.88em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>に対して初期状態は次のようになる:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">main</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext></mrow><mo stretchy="false">)</mo><mtext> </mtext><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><msub><mrow><mi>a</mi><mi>s</mi></mrow><mrow><mi>i</mi><mi>n</mi></mrow></msub><mo separator="true">,</mo><msub><mrow><mi>r</mi><mi>s</mi></mrow><mrow><mi>i</mi><mi>n</mi></mrow></msub><mo separator="true">,</mo><msub><mrow><mi>u</mi><mi>s</mi></mrow><mrow><mi>i</mi><mi>n</mi></mrow></msub><mo separator="true">,</mo><msub><mi>h</mi><mrow><mi>i</mi><mi>n</mi></mrow></msub><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mtable columnalign="left left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><msub><mrow><mi>a</mi><mi>s</mi></mrow><mrow><mi>i</mi><mi>n</mi></mrow></msub></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><msub><mrow><mi>r</mi><mi>s</mi></mrow><mrow><mi>i</mi><mi>n</mi></mrow></msub></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><msub><mrow><mi>u</mi><mi>s</mi></mrow><mrow><mi>i</mi><mi>n</mi></mrow></msub></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><msub><mi>h</mi><mrow><mi>i</mi><mi>n</mi></mrow></msub></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mn>1</mn></msub><mo>↦</mo><mo stretchy="false">⟨</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">\</mtext><msub><mi>π</mi><mn>1</mn></msub></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mn>1</mn></msub><mo separator="true">,</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>s</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mn>1</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">⟩</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi><mi mathvariant="normal">⋮</mi><mpadded height="0em" voffset="0em"><mspace height="1.5em" mathbackground="black" width="0em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mi>n</mi></msub><mo>↦</mo><mo stretchy="false">⟨</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">\</mtext><msub><mi>π</mi><mi>n</mi></msub></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mi>n</mi></msub><mo separator="true">,</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>s</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mi>n</mi></msub><mo stretchy="false">)</mo><mo stretchy="false">⟩</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi>σ</mi></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>=</mo><mo stretchy="false">[</mo><msub><mi>g</mi><mn>1</mn></msub><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mn>1</mn></msub><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><msub><mi>g</mi><mi>n</mi></msub><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mi>n</mi></msub><mo stretchy="false">]</mo></mrow></mstyle></mtd></mtr></mtable></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{l}
\langle \mathbf{Eval}\,(\text{\tt main \{\}})\,[]\rangle(
\mathit{as}_\mathit{in},
\mathit{rs}_\mathit{in},
\mathit{us}_\mathit{in},
h_\mathit{in},
\sigma
) \\
\begin{array}{ll}
\mathit{as}_\mathit{in} &= [] \\
\mathit{rs}_\mathit{in} &= [] \\
\mathit{us}_\mathit{in} &= [] \\
h_\mathit{in} &= \left[\begin{matrix}
a_1 \mapsto \langle\mathit{vs}_1 \mathrel{\text{\tt \textbackslash}\pi_1} \mathit{xs}_1 \mathrel{\text{\tt ->}} e_1, \mathit{vals}(\langle [], \sigma\rangle, \mathit{vs}_1)\rangle \\
\vdots \\
a_n \mapsto \langle\mathit{vs}_n \mathrel{\text{\tt \textbackslash}\pi_n} \mathit{xs}_n \mathrel{\text{\tt ->}} e_n, \mathit{vals}(\langle [], \sigma\rangle, \mathit{vs}_n)\rangle
\end{matrix}\right] \\
\sigma &= [g_1 \mapsto \mathbf{Addr}\,a_1, \ldots, g_n \mapsto \mathbf{Addr}\,a_n]
\end{array}
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:10.26em;vertical-align:-4.88em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.38em;"><span style="top:-11.32em;"><span class="pstrut" style="height:6.78em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">main {}</span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]⟩</span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathit">as</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3088em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">in</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">rs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3088em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">in</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">us</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3088em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">in</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3088em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">in</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-6.18em;"><span class="pstrut" style="height:6.78em;"></span><span class="mord"><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.78em;"><span style="top:-8.32em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">as</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3088em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">in</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-7.12em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">rs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3088em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">in</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-5.92em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">us</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3088em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">in</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.18em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3088em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">in</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-0.46em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.28em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.78em;"><span style="top:-8.32em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mclose">]</span></span></span><span style="top:-7.12em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mclose">]</span></span></span><span style="top:-5.92em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mclose">]</span></span></span><span style="top:-3.18em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-4.35em;"><span class="pstrut" style="height:6.2em;"></span><span style="width:0.667em;height:4.200em;"><svg height="4.200em" viewbox="0 0 667 4200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.38em;"><span style="top:-5.2275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vals</span></span><span class="mopen">(⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)⟩</span></span></span><span style="top:-3.3675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-2.1675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vals</span></span><span class="mopen">(⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)⟩</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.88em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-4.35em;"><span class="pstrut" style="height:6.2em;"></span><span style="width:0.667em;height:4.200em;"><svg height="4.200em" viewbox="0 0 667 4200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-0.46em;"><span class="pstrut" style="height:4.38em;"></span><span class="mord"><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.28em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.88em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>最初はトップレベルの束縛の中に <tt class="docutils literal">main</tt> 関数がある前提でそこから評価を始める.ここは本質じゃないので, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>g</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">g_1</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> とかから始めてもいい.トップレベルの束縛は, letrec 式に相当するので,自由変数の部分にトップレベルから取ってきたものをあてがって,ヒープに入れておく.</p>
<p>この状態から状態遷移を始めていく.</p>
</div>
<div class="section" id="auto-id-11">
<h3>評価<a class="headerlink" href="#auto-id-11" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>まず, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><annotation encoding="application/x-tex">\mathbf{Eval}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">Eval</span></span></span></span></span></span> 命令の遷移から見ていく.基本的に STG のそれぞれの式に対して,それに合う遷移をしていく.その定義は,以下のようになる:</p>
<dl class="docutils">
<dt>let (rec) 式</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mrow><mo fence="true">(</mo><mtable columnalign="left center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mtext mathvariant="monospace">let</mtext></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>x</mi><mn>1</mn></msub><mo>=</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">\</mtext><msub><mi>π</mi><mn>1</mn></msub></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mn>1</mn></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mi><mi mathvariant="normal">⋮</mi><mpadded height="0em" voffset="0em"><mspace height="1.5em" mathbackground="black" width="0em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>x</mi><mi>n</mi></msub><mo>=</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">\</mtext><msub><mi>π</mi><mi>n</mi></msub></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mi>n</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">in</mtext><mtext> </mtext><mi>e</mi></mrow></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mi>e</mi><mtext> </mtext><msup><mi>ρ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><msup><mi>ρ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><mi>ρ</mi><mrow><mo fence="true">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>x</mi><mn>1</mn></msub><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mn>1</mn></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi><mi mathvariant="normal">⋮</mi><mpadded height="0em" voffset="0em"><mspace height="1.5em" mathbackground="black" width="0em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>x</mi><mi>n</mi></msub><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mi>n</mi></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><mi>h</mi><mrow><mo fence="true">[</mo><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mn>1</mn></msub><mo>↦</mo><mo stretchy="false">⟨</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">\</mtext><msub><mi>π</mi><mn>1</mn></msub></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mn>1</mn></msub><mo separator="true">,</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>s</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><msub><mi>ρ</mi><mrow><mi>r</mi><mi>h</mi><mi>s</mi></mrow></msub><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo separator="true">,</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mn>1</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">⟩</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi><mi mathvariant="normal">⋮</mi><mpadded height="0em" voffset="0em"><mspace height="1.5em" mathbackground="black" width="0em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mi>n</mi></msub><mo>↦</mo><mo stretchy="false">⟨</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">\</mtext><msub><mi>π</mi><mi>n</mi></msub></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mi>n</mi></msub><mo separator="true">,</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>s</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><msub><mi>ρ</mi><mrow><mi>r</mi><mi>h</mi><mi>s</mi></mrow></msub><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo separator="true">,</mo><msub><mrow><mi>v</mi><mi>s</mi></mrow><mi>n</mi></msub><mo stretchy="false">)</mo><mo stretchy="false">⟩</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><msub><mi>ρ</mi><mrow><mi>r</mi><mi>h</mi><mi>s</mi></mrow></msub><mo>=</mo><mi>ρ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle \mathbf{Eval}\,\left(\begin{array}{lc}
\text{\tt let}
&x_1 = \mathit{vs}_1 \mathrel{\text{\tt \textbackslash}\pi_1} \mathit{xs}_1 \mathrel{\text{\tt ->}} e_1 \\
&\vdots \\
&x_n = \mathit{vs}_n \mathrel{\text{\tt \textbackslash}\pi_n} \mathit{xs}_n \mathrel{\text{\tt ->}} e_n \\
\text{\tt in}\,e
\end{array}\right)\,\rho\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle \mathbf{Eval}\,e\,\rho'\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h',
\sigma
) \\
(\rho' = \rho\left[\begin{array}{c}
x_1 \mapsto \mathbf{Addr}\,a_1 \\
\vdots \\
x_n \mapsto \mathbf{Addr}\,a_n
\end{array}\right]
, h' = h\left[\begin{array}{c}
a_1 \mapsto \langle \mathit{vs}_1 \mathrel{\text{\tt \textbackslash}\pi_1} \mathit{xs}_1 \mathrel{\text{\tt ->}} e_1, \mathit{vals}(\langle \rho_{\mathit{rhs}}, []\rangle, \mathit{vs}_1)\rangle \\
\vdots \\
a_n \mapsto \langle \mathit{vs}_n \mathrel{\text{\tt \textbackslash}\pi_n} \mathit{xs}_n \mathrel{\text{\tt ->}} e_n, \mathit{vals}(\langle \rho_{\mathit{rhs}}, []\rangle, \mathit{vs}_n)\rangle
\end{array}\right]
, \rho_\mathit{rhs} = \rho
)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:9.72em;vertical-align:-4.61em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.11em;"><span style="top:-7.11em;"><span class="pstrut" style="height:4.98em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.95em;"><span style="top:-4.95em;"><span class="pstrut" style="height:7.4em;"></span><span style="width:0.875em;height:5.400em;"><svg height="5.400em" viewbox="0 0 875 5400" width="0.875em" xmlns="http://www.w3.org/2000/svg"><path d="M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1
c-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,
-36,557 l0,1884c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,
949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9
c0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,
-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189
l0,-1892c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,
-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.45em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.98em;"><span style="top:-5.64em;"><span class="pstrut" style="height:3.5em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">let</span></span></span></span></span><span style="top:-3.78em;"><span class="pstrut" style="height:3.5em;"></span><span class="mord"></span></span><span style="top:-2.58em;"><span class="pstrut" style="height:3.5em;"></span><span class="mord"></span></span><span style="top:-1.38em;"><span class="pstrut" style="height:3.5em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">in</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.48em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.98em;"><span style="top:-5.8275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.9675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-2.7675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.28em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.95em;"><span style="top:-4.95em;"><span class="pstrut" style="height:7.4em;"></span><span style="width:0.875em;height:5.400em;"><svg height="5.400em" viewbox="0 0 875 5400" width="0.875em" xmlns="http://www.w3.org/2000/svg"><path d="M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,
63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5
c11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0,1809
c-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664
c-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11
c0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17
c242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558
l0,-1944c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,
-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.45em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:4.98em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-4.35em;"><span class="pstrut" style="height:6.2em;"></span><span style="width:0.667em;height:4.200em;"><svg height="4.200em" viewbox="0 0 667 4200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.38em;"><span style="top:-5.2275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.3675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-2.1675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.88em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-4.35em;"><span class="pstrut" style="height:6.2em;"></span><span style="width:0.667em;height:4.200em;"><svg height="4.200em" viewbox="0 0 667 4200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-4.35em;"><span class="pstrut" style="height:6.2em;"></span><span style="width:0.667em;height:4.200em;"><svg height="4.200em" viewbox="0 0 667 4200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.38em;"><span style="top:-5.2275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vals</span></span><span class="mopen">(⟨</span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathit mtight">rhs</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)⟩</span></span></span><span style="top:-3.3675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-2.1675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\</span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vals</span></span><span class="mopen">(⟨</span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathit mtight">rhs</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)⟩</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.88em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-4.35em;"><span class="pstrut" style="height:6.2em;"></span><span style="width:0.667em;height:4.200em;"><svg height="4.200em" viewbox="0 0 667 4200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">rhs</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.61em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">letrec 式の場合は, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>ρ</mi><mrow><mi>r</mi><mi>h</mi><mi>s</mi></mrow></msub><mo>=</mo><msup><mi>ρ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">\rho_\mathit{rhs} = \rho'</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathit mtight">rhs</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9463em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span> とする.この遷移は,単純に let で指定されたローカルのクロージャをヒープに確保し,そのアドレスを変数に結びつけるだけ. let と letrec の違いは作るクロージャでキャプチャするアドレスの違いで, let の場合は前の環境から, letrec の場合は今回確保したアドレスも含めてキャプチャする.</p>
</dd>
<dt>case 式</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mtext mathvariant="monospace">case</mtext><mtext> </mtext><mi>e</mi><mtext> </mtext><mtext mathvariant="monospace">of</mtext><mtext> </mtext><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mi>e</mi><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>ρ</mi><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\langle \mathbf{Eval}\,(\text{\tt case}\,e\,\text{\tt of}\,\mathit{alts})\,\rho\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle \mathbf{Eval}\,e\,\rho\rangle(
\mathit{as},
\langle\mathit{alts}, \rho\rangle\mathbin{:}\mathit{rs},
\mathit{us},
h,
\sigma
)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">case</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">of</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">alts</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">alts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span></span></span></div>
<p class="last">この遷移では,分岐の継続を返り値スタックに積んだ後,対象の式の評価に移る.最終的に <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnCon}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnCon</span></span></span></span></span></span> とか <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnInt}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnInt</span></span></span></span></span></span> で帰ってきて,元の環境で継続に復帰する.</p>
</dd>
<dt>適用</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mi>f</mi><mtext> </mtext><mrow><mi>x</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><msup><mi>s</mi><mo lspace="0em" mathvariant="italic" rspace="0em">′</mo></msup></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mi>f</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo separator="true">,</mo><mrow><mi>a</mi><msup><mi>s</mi><mo lspace="0em" mathvariant="italic" rspace="0em">′</mo></msup></mrow><mo>=</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>s</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mrow><mi>x</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><mrow><mi>a</mi><mi>s</mi></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mi>v</mi><mtext> </mtext><mo stretchy="false">{</mo><mo stretchy="false">}</mo><mo stretchy="false">)</mo><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mi>n</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mi>n</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle \mathbf{Eval}\,(f\,\mathit{xs})\,\rho\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle \mathbf{Enter}\,a\rangle(
\mathit{as'},
\mathit{rs},
\mathit{us},
h,
\sigma
) \\
(\mathit{val}(\langle \rho, \sigma\rangle, f) = \mathbf{Addr}\,a, \mathit{as'} = \mathit{vals}(\langle \rho, \sigma\rangle, \mathit{xs}) \mathbin{++} \mathit{as}) \\
\\
\langle \mathbf{Eval}\,(v\,\{\})\,\rho\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle \mathbf{ReturnInt}\,n\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
) \\
(\mathit{val}(\langle \rho, \sigma\rangle, v) = \mathbf{Int}\,n)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:6em;vertical-align:-2.75em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">a</span><span class="mord"><span class="mord mathit">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathit">val</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">a</span><span class="mord"><span class="mord mathit">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">vals</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">as</span></span><span class="mclose">)</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">{</span><span class="mclose">})</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnInt</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathit">val</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">変数への適用の場合 2 種類あって,クロージャへ引数を適用する場合とプリミティブ整数の評価の場合.クロージャの場合変数には <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><annotation encoding="application/x-tex">\mathbf{Addr}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span></span></span></span></span> が結びついていて,プリミティブ整数の場合 <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{Int}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Int</span></span></span></span></span></span> が結びついてる.クロージャの場合,引数を引数スタックに積み込んで適用に移る.プリミティブ整数の場合,そのまま継続への復帰に遷移する.</p>
</dd>
<dt>コンストラクタ適用</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mi>c</mi><mtext> </mtext><mrow><mi>x</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mi>c</mi><mtext> </mtext><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>s</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mrow><mi>x</mi><mi>s</mi></mrow><mo stretchy="false">)</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">
\langle \mathbf{Eval}\,(c\,\mathit{xs})\,\rho\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle \mathbf{ReturnCon}\,c\,\mathit{vals}(\langle \rho, \sigma\rangle, \mathit{xs})\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vals</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mclose">)⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span></span></span></div>
<p class="last">コンストラクタへの適用は,単純に適用された変数から値を持ってきて,継続へ復帰するだけ.</p>
</dd>
<dt>プリミティブ</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mi>n</mi><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mi>n</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mo>⊕</mo><mtext> </mtext><mo stretchy="false">{</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>x</mi><mn>2</mn></msub><mo stretchy="false">}</mo><mo stretchy="false">)</mo><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><msub><mi>i</mi><mn>1</mn></msub><mo>⊕</mo><msub><mi>i</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mi>v</mi><mi>a</mi><mi>l</mi><mi>s</mi></mrow><mo stretchy="false">(</mo><mo stretchy="false">⟨</mo><mi>ρ</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mo stretchy="false">{</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>x</mi><mn>2</mn></msub><mo stretchy="false">}</mo><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><msub><mi>i</mi><mn>1</mn></msub><mo separator="true">,</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><msub><mi>i</mi><mn>2</mn></msub><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle \mathbf{Eval}\,n\,\rho\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle \mathbf{ReturnInt}\,n\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
) \\
\\
\langle \mathbf{Eval}\,(\oplus\,\{x_1, x_2\})\,\rho\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle \mathbf{ReturnInt}\,(i_1 \oplus i_2)\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
) \\
(\mathit{vals}(\langle \rho, \sigma\rangle, \{x_1, x_2\}) = [\mathbf{Int}\,i_1, \mathbf{Int}\,i_2])
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:4.8em;vertical-align:-2.15em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnInt</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">⊕</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">})</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnInt</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">i</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">i</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathit">vals</span></span><span class="mopen">(⟨</span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">})</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">i</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">i</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">])</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">プリミティブ整数やプリミティブ演算は,そのまま継続へ復帰するだけ. STG では必ず評価は case 式でのみ行われるので,プリミティブ演算の引数にサンクは入ってこないことに注意.サンクを入れたい場合, case でサンクを潰した後それを束縛して渡してやる必要がある.</p>
</dd>
</dl>
</div>
<div class="section" id="auto-id-12">
<h3>適用<a class="headerlink" href="#auto-id-12" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>次に, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><annotation encoding="application/x-tex">\mathbf{Enter}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Enter</span></span></span></span></span></span> 命令の遷移から見ていく. <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><annotation encoding="application/x-tex">\mathbf{Enter}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">Enter</span></span></span></span></span></span> 命令は,引数が充足してる場合は更新フラグを見て,いい感じに処理をする.その定義は,以下のようになる.</p>
<dl class="docutils">
<dt>更新不要クロージャ</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mi>e</mi><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><msup><mi>s</mi><mo lspace="0em" mathvariant="italic" rspace="0em">′</mo></msup></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>a</mi></msub><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><mrow><mi>a</mi><msup><mi>s</mi><mo lspace="0em" mathvariant="italic" rspace="0em">′</mo></msup></mrow><mo>=</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi mathvariant="normal">∣</mi><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>a</mi></msub><mi mathvariant="normal">∣</mi><mo>=</mo><mi mathvariant="normal">∣</mi><mrow><mi>x</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi><mo separator="true">,</mo><mi>ρ</mi><mo>=</mo><mo stretchy="false">[</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo>↦</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>f</mi></msub><mo separator="true">,</mo><mrow><mi>x</mi><mi>s</mi></mrow><mo>↦</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>a</mi></msub><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>h</mi><mo stretchy="false">(</mo><mi>a</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">⟨</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">\n</mtext></mo><mrow><mi>x</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">-></mtext></mo><mi>e</mi><mo separator="true">,</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>f</mi></msub><mo stretchy="false">⟩</mo><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle\mathbf{Enter}\,a\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle\mathbf{Eval}\,e\,\rho\rangle(
\mathit{as'},
\mathit{rs},
\mathit{us},
h,
\sigma
) \\
( \mathit{ws}_a \mathbin{++} \mathit{as'} = \mathit{as}
, |\mathit{ws}_a| = |\mathit{xs}|
, \rho = [\mathit{vs} \mapsto \mathit{ws}_f, \mathit{xs} \mapsto \mathit{ws}_a]
, h(a) = \langle\mathit{vs} \mathrel{\text{\tt \textbackslash n}} \mathit{xs} \mathrel{\text{\tt ->}} e, \mathit{ws}_f\rangle
)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">a</span><span class="mord"><span class="mord mathit">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">a</span><span class="mord"><span class="mord mathit">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∣</span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">xs</span></span><span class="mord">∣</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\n</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">⟩)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">引数が充足してて更新不要なクロージャの場合,単なる関数適用を行う.環境はキャプチャしておいた自由変数と,引数の変数分を作って渡す.なお,論文中だとヒープからクロージャのアドレスを抜き去ってるように見えるんだが,大丈夫なんだろか.とりあえず,こっちでは修正しといた.ただ,表記法が定義されてないので,解釈違いかもしれん.</p>
</dd>
<dt>更新可能クロージャ</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo stretchy="false">[</mo><mi>a</mi><mo>↦</mo><mo stretchy="false">⟨</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">\u</mtext></mo><mo stretchy="false">{</mo><mo stretchy="false">}</mo><mo><mtext mathvariant="monospace">-></mtext></mo><mi>e</mi><mo separator="true">,</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>f</mi></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mi>e</mi><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>a</mi><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mi>ρ</mi><mo>=</mo><mo stretchy="false">[</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo>↦</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>f</mi></msub><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle\mathbf{Enter}\,a\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h[a \mapsto \langle\mathit{vs} \mathrel{\text{\tt \textbackslash u}} \{\} \mathrel{\text{\tt ->}} e, \mathit{ws}_f\rangle],
\sigma
)
\Rightarrow
\langle\mathbf{Eval}\,e\,\rho\rangle(
[],
[],
\langle\mathit{as}, \mathit{rs}, a\rangle \mathbin{:} \mathit{us},
h,
\sigma
) \\
(\rho = [\mathit{vs} \mapsto \mathit{ws}_f])
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\u</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">])</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">更新が必要なクロージャ,つまりサンクは,古いクロージャのアドレスをヒープから消し,更新スタックに情報を退避させて,評価を行う.ところで,この時もし古いクロージャのアドレスにアクセスして評価するような STG プログラムがあれば,そのアドレスを消してしまっていると問題が起きる.ただ,更新中に更新してるクロージャに再度アクセスがあるということは,つまり無限ループが発生してるってことでもある.これは論文中ではブラックホールと呼ばれていて,実際の実行マシンではこれを検出し,エラーを出すようにしてる.</p>
</dd>
<dt>部分適用</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">⟨</mo><msub><mrow><mi>a</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mrow><mi>r</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mi>a</mi><mi>u</mi></msub><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><msub><mrow><mi>a</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mrow><mi>r</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo fence="true">(</mo><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>h</mi><mo stretchy="false">(</mo><mi>a</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">⟨</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">\n</mtext></mo><mrow><mi>x</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">-></mtext></mo><mi>e</mi><mo separator="true">,</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>f</mi></msub><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mi mathvariant="normal">∣</mi><mrow><mi>a</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi><mo><</mo><mi mathvariant="normal">∣</mi><mrow><mi>x</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>2</mn></msub><mo>=</mo><mrow><mi>x</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi mathvariant="normal">∣</mi><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mi mathvariant="normal">∣</mi><mo>=</mo><mi mathvariant="normal">∣</mi><mrow><mi>a</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>a</mi><mi>u</mi></msub><mo>↦</mo><mo stretchy="false">⟨</mo><mo stretchy="false">(</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo stretchy="false">)</mo><mo><mtext mathvariant="monospace">\n</mtext></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>2</mn></msub><mo><mtext mathvariant="monospace">-></mtext></mo><mi>e</mi><mo separator="true">,</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>f</mi></msub><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><mrow><mi>a</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle\mathbf{Enter}\,a\rangle(
\mathit{as},
[],
\langle \mathit{as}_u, \mathit{rs}_u, a_u\rangle\mathbin{:}\mathit{us},
h,
\sigma
)
\Rightarrow
\langle\mathbf{Enter}\,a\rangle(
\mathit{as} \mathbin{++} \mathit{as}_u,
\mathit{rs}_u,
\mathit{us},
h',
\sigma
) \\
\left(\begin{array}{c}
h(a) = \langle \mathit{vs}\mathrel{\text{\tt \textbackslash n}}\mathit{xs}\mathrel{\text{\tt ->}} e, \mathit{ws}_f\rangle,
|\mathit{as}| < |\mathit{xs}| \\
\mathit{xs}_1 \mathbin{++} \mathit{xs}_2 = \mathit{xs},
|\mathit{xs}_1| = |\mathit{as}|,
h' = h[a_u \mapsto \langle (\mathit{vs} \mathbin{++} \mathit{xs}_1)\mathrel{\text{\tt \textbackslash n}}\mathit{xs}_2\mathrel{\text{\tt ->}} e, \mathit{ws}_f \mathbin{++} \mathit{as}\rangle]
\end{array}\right)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.66em;"><span class="pstrut" style="height:3.45em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord"><span class="mord mathit">as</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">rs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord"><span class="mord mathit">as</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">rs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-2.85em;"><span class="pstrut" style="height:3.45em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\n</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">as</span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">xs</span></span><span class="mord">∣</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∣</span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">as</span></span><span class="mord">∣</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨(</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\n</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">as</span></span><span class="mclose">⟩]</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>引数スタックの要素の数が,クロージャに必要な引数の数に満たない時は,クロージャへの適用は部分適用扱いになる.部分適用の場合,部分適用を表すサンクの評価中なはずなので,サンクの内容を既に分かっている部分はキャプチャして,本来の引数の数を受け取る関数を表すクロージャに更新する.そして,サンクに適用されたはずの引数を退避させた更新スタックから取り出してきて,もう一度適用をやり直す.</p>
<p>意味論上はこの規則で問題ないのだが,実装する時のことを考えると, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo stretchy="false">)</mo><mo><mtext mathvariant="monospace">\n</mtext></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>2</mn></msub><mo><mtext mathvariant="monospace">-></mtext></mo><mi>e</mi></mrow><annotation encoding="application/x-tex">(\mathit{vs} \mathbin{++} \mathit{xs}_1)\mathrel{\text{\tt \textbackslash n}}\mathit{xs}_2\mathrel{\text{\tt ->}} e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\n</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> というクロージャを部分適用の際に作成するのはかなりめんどくさい.クロージャの中身はコンパイル時に通常生成されるわけだが,この場合動的に生成する必要が出てくる.または,全ての部分適用を想定して, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>e</mi></mrow><annotation encoding="application/x-tex">e</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">e</span></span></span></span></span> 度に専用のクロージャコードをコンパイル時に生成するという方法も考えられる (普通はこちらが正攻法になる) .ただ,もちろんそれはコンパイル時生成コードが大量に出てくるので避けたい.そこで,規則を以下のように変えることが考えられる:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">⟨</mo><msub><mrow><mi>a</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mrow><mi>r</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mi>a</mi><mi>u</mi></msub><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><msub><mrow><mi>a</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mrow><mi>r</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo fence="true">(</mo><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>h</mi><mo stretchy="false">(</mo><mi>a</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">⟨</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">\n</mtext></mo><mrow><mi>x</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">-></mtext></mo><mi>e</mi><mo separator="true">,</mo><msub><mrow><mi>w</mi><mi>s</mi></mrow><mi>f</mi></msub><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mi mathvariant="normal">∣</mi><mrow><mi>a</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi><mo><</mo><mi mathvariant="normal">∣</mi><mrow><mi>x</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo lspace="0.22em" rspace="0.22em"><mo>+</mo><mo>+</mo></mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>2</mn></msub><mo>=</mo><mrow><mi>x</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi mathvariant="normal">∣</mi><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mi mathvariant="normal">∣</mi><mo>=</mo><mi mathvariant="normal">∣</mi><mrow><mi>a</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>a</mi><mi>u</mi></msub><mo>↦</mo><mo stretchy="false">⟨</mo><mo stretchy="false">(</mo><mi>f</mi><mo lspace="0.22em" rspace="0.22em">:</mo><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo stretchy="false">)</mo><mo><mtext mathvariant="monospace">\n</mtext></mo><mtext mathvariant="monospace">{}</mtext><mo><mtext mathvariant="monospace">-></mtext></mo><mi>f</mi><mtext> </mtext><msub><mrow><mi>x</mi><mi>s</mi></mrow><mn>1</mn></msub><mo separator="true">,</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mi>f</mi></mstyle><mtext> は fresh な変数</mtext></mrow></mrow></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle\mathbf{Enter}\,a\rangle(
\mathit{as},
[],
\langle \mathit{as}_u, \mathit{rs}_u, a_u\rangle\mathbin{:}\mathit{us},
h,
\sigma
)
\Rightarrow
\langle\mathbf{Enter}\,a\rangle(
\mathit{as} \mathbin{++} \mathit{as}_u,
\mathit{rs}_u,
\mathit{us},
h',
\sigma
) \\
\left(\begin{array}{c}
h(a) = \langle \mathit{vs}\mathrel{\text{\tt \textbackslash n}}\mathit{xs}\mathrel{\text{\tt ->}} e, \mathit{ws}_f\rangle,
|\mathit{as}| < |\mathit{xs}| \\
\mathit{xs}_1 \mathbin{++} \mathit{xs}_2 = \mathit{xs},
|\mathit{xs}_1| = |\mathit{as}|,
h' = h[a_u \mapsto \langle (f \mathbin{:} \mathit{xs}_1)\mathrel{\text{\tt \textbackslash n}}\text{\tt \{\}}\mathrel{\text{\tt ->}} f\,\mathit{xs}_1, \mathbf{Addr}\,a \mathbin{:} \mathit{as}\rangle],
\text{\(f\) は fresh な変数}
\end{array}\right)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.66em;"><span class="pstrut" style="height:3.45em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord"><span class="mord mathit">as</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">rs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord"><span class="mord mathit">as</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">rs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-2.85em;"><span class="pstrut" style="height:3.45em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\n</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">ws</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">as</span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">xs</span></span><span class="mord">∣</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord">+</span><span class="mord">+</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">xs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∣</span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">as</span></span><span class="mord">∣</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\n</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">{}</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">xs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">as</span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord"> </span><span class="mord cjk_fallback">は</span><span class="mord"> fresh </span><span class="mord cjk_fallback">な変数</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">こうしておくと,部分適用用のクロージャを作っておくだけで,それを共有することができ,コード生成量もその手間も削減することができる.クロージャへのエントリが 1 回増えるが,そこら辺はより低レベルの最適化で消えることも期待できる.</p>
</dd>
</dl>
</div>
<div class="section" id="auto-id-13">
<h3>継続への復帰<a class="headerlink" href="#auto-id-13" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>最後に, <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnCon}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnCon</span></span></span></span></span></span> 命令 / <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnInt}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnInt</span></span></span></span></span></span> 命令の遷移から見ていく.継続への復帰は,両命令でやってることは同じなので,まず <span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnCon}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnCon</span></span></span></span></span></span> 命令だけ見ていく.その定義は,以下のようになる.</p>
<dl class="docutils">
<dt>マッチする場合</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mi>c</mi><mtext> </mtext><mrow><mi>w</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>ρ</mi><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mi>e</mi><mtext> </mtext><mi>ρ</mi><mo stretchy="false">[</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo>↦</mo><mrow><mi>w</mi><mi>s</mi></mrow><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo>=</mo><mo>⋯</mo><mo lspace="0.22em" rspace="0.22em" separator="true">;</mo><mi>c</mi><mtext> </mtext><mrow><mi>v</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">-></mtext></mo><mi>e</mi><mo lspace="0.22em" rspace="0.22em" separator="true">;</mo><mo>⋯</mo><mtext> </mtext><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle\mathbf{ReturnCon}\,c\,\mathit{ws}\rangle(
\mathit{as},
\langle \mathit{alts}, \rho\rangle\mathbin{:}\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle\mathbf{Eval}\,e\,\rho[\mathit{vs} \mapsto \mathit{ws}]\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
) \\
(\mathit{alts} = \cdots\mathbin{;} c\,\mathit{vs}\mathrel{\text{\tt ->}}e\mathbin{;} \cdots)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ws</span></span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">alts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mopen">[</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathit">ws</span></span><span class="mclose">]⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathit">alts</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">e</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mpunct">;</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">継続のパターンマッチの中に該当するコンストラクタに対する継続があるときは,その継続に復帰する.</p>
</dd>
<dt>デフォルトケースの場合</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mi>c</mi><mtext> </mtext><mrow><mi>w</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>ρ</mi><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><msub><mi>e</mi><mi>d</mi></msub><mtext> </mtext><mi>ρ</mi><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo>=</mo><mrow><mo fence="true">(</mo><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>c</mi><mn>1</mn></msub><mtext> </mtext><msub><mrow><mi>v</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mn>1</mn></msub><mo lspace="0.22em" rspace="0.22em" separator="true">;</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi><mi mathvariant="normal">⋮</mi><mpadded height="0em" voffset="0em"><mspace height="1.5em" mathbackground="black" width="0em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>c</mi><mi>n</mi></msub><mtext> </mtext><msub><mrow><mi>v</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mi>n</mi></msub><mo lspace="0.22em" rspace="0.22em" separator="true">;</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">default</mtext><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mi>d</mi></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow><mo separator="true">,</mo><mi mathvariant="normal">∀</mi><mn>1</mn><mo>≤</mo><mi>i</mi><mo>≤</mo><mi>n</mi><mo separator="true">.</mo><mi>c</mi><mo mathvariant="normal">≠</mo><msub><mi>c</mi><mi>i</mi></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle\mathbf{ReturnCon}\,c\,\mathit{ws}\rangle(
\mathit{as},
\langle \mathit{alts}, \rho\rangle\mathbin{:}\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle\mathbf{Eval}\,e_d\,\rho\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h,
\sigma
) \\
(\mathit{alts} = \left(\begin{array}{c}
c_1\,\mathit{vs}_1\mathrel{\text{\tt ->}}e_1\mathbin{;} \\
\vdots \\
c_n\,\mathit{vs}_n\mathrel{\text{\tt ->}}e_n\mathbin{;} \\
\text{\tt default}\mathrel{\text{\tt ->}}e_d
\end{array}\right), \forall 1 \leq i \leq n\ldotp c \neq c_i)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:6.66em;vertical-align:-3.08em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.58em;"><span style="top:-7.72em;"><span class="pstrut" style="height:4.98em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ws</span></span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">alts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-4.38em;"><span class="pstrut" style="height:4.98em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathit">alts</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.95em;"><span style="top:-4.95em;"><span class="pstrut" style="height:7.4em;"></span><span style="width:0.875em;height:5.400em;"><svg height="5.400em" viewbox="0 0 875 5400" width="0.875em" xmlns="http://www.w3.org/2000/svg"><path d="M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1
c-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,
-36,557 l0,1884c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,
949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9
c0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,
-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189
l0,-1892c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,
-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.45em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.98em;"><span style="top:-5.8275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mpunct">;</span></span></span></span><span style="top:-3.9675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-2.7675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mpunct">;</span></span></span></span><span style="top:-1.5675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">default</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.48em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.95em;"><span style="top:-4.95em;"><span class="pstrut" style="height:7.4em;"></span><span style="width:0.875em;height:5.400em;"><svg height="5.400em" viewbox="0 0 875 5400" width="0.875em" xmlns="http://www.w3.org/2000/svg"><path d="M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,
63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5
c11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0,1809
c-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664
c-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11
c0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17
c242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558
l0,-1944c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,
-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.45em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∀1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">n</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.08em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">コンストラクタにパターンマッチするものがなくて,デフォルトケースでの継続があるときは,その継続に復帰する.</p>
</dd>
<dt>デフォルトケースでの束縛</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mi>c</mi><mtext> </mtext><mrow><mi>w</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>ρ</mi><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><msub><mi>e</mi><mi>d</mi></msub><mtext> </mtext><msup><mi>ρ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mrow><mi>a</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>r</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo fence="true">(</mo><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mi>a</mi><mi>l</mi><mi>t</mi><mi>s</mi></mrow><mo>=</mo><mrow><mo fence="true">(</mo><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>c</mi><mn>1</mn></msub><mtext> </mtext><msub><mrow><mi>v</mi><mi>s</mi></mrow><mn>1</mn></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mn>1</mn></msub><mo lspace="0.22em" rspace="0.22em" separator="true">;</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mi><mi mathvariant="normal">⋮</mi><mpadded height="0em" voffset="0em"><mspace height="1.5em" mathbackground="black" width="0em"></mspace></mpadded></mi></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>c</mi><mi>n</mi></msub><mtext> </mtext><msub><mrow><mi>v</mi><mi>s</mi></mrow><mi>n</mi></msub><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mi>n</mi></msub><mo lspace="0.22em" rspace="0.22em" separator="true">;</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>v</mi><mo><mtext mathvariant="monospace">-></mtext></mo><msub><mi>e</mi><mi>d</mi></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow><mo separator="true">,</mo><mi mathvariant="normal">∀</mi><mn>1</mn><mo>≤</mo><mi>i</mi><mo>≤</mo><mi>n</mi><mo separator="true">.</mo><mi>c</mi><mo mathvariant="normal">≠</mo><msub><mi>c</mi><mi>i</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msup><mi>ρ</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><mi>ρ</mi><mo stretchy="false">[</mo><mi>v</mi><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><mi>a</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><mi>h</mi><mo stretchy="false">[</mo><mi>a</mi><mo>↦</mo><mo stretchy="false">⟨</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">\n</mtext></mo><mo stretchy="false">{</mo><mo stretchy="false">}</mo><mo><mtext mathvariant="monospace">-></mtext></mo><mi>c</mi><mtext> </mtext><mrow><mi>v</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>w</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>v</mi><mi>s</mi></mrow></mstyle><mtext> は </mtext><mstyle displaystyle="false" scriptlevel="0"><mi mathvariant="normal">∣</mi><mrow><mi>v</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi><mo>=</mo><mi mathvariant="normal">∣</mi><mrow><mi>w</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi></mstyle><mtext> を満たす fresh な変数列</mtext></mrow></mstyle></mtd></mtr></mtable><mo fence="true">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle\mathbf{ReturnCon}\,c\,\mathit{ws}\rangle(
\mathit{as},
\langle \mathit{alts}, \rho\rangle\mathbin{:}\mathit{rs},
\mathit{us},
h,
\sigma
)
\Rightarrow
\langle\mathbf{Eval}\,e_d\,\rho'\rangle(
\mathit{as},
\mathit{rs},
\mathit{us},
h',
\sigma
) \\
\left(\begin{array}{c}
\mathit{alts} = \left(\begin{array}{c}
c_1\,\mathit{vs}_1\mathrel{\text{\tt ->}}e_1\mathbin{;} \\
\vdots \\
c_n\,\mathit{vs}_n\mathrel{\text{\tt ->}}e_n\mathbin{;} \\
v\mathrel{\text{\tt ->}}e_d
\end{array}\right),
\forall 1 \leq i \leq n\ldotp c \neq c_i \\
\rho' = \rho[v \mapsto \mathbf{Addr}\,a],
h' = h[a \mapsto \langle \mathit{vs}\mathrel{\text{\tt \textbackslash n}}\{\}\mathrel{\text{\tt ->}}c\,\mathit{vs}, \mathit{ws}\rangle] \\
\text{\(\mathit{vs}\) は \(|\mathit{vs}| = |\mathit{ws}|\) を満たす fresh な変数列}
\end{array}\right)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:9.06em;vertical-align:-4.28em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.78em;"><span style="top:-10.12em;"><span class="pstrut" style="height:6.18em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ws</span></span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">alts</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord mathit">as</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">rs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-5.58em;"><span class="pstrut" style="height:6.18em;"></span><span class="mord"><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.1499em;"><span style="top:-6.1499em;"><span class="pstrut" style="height:9.8em;"></span><span style="width:0.875em;height:7.800em;"><svg height="7.800em" viewbox="0 0 875 7800" width="0.875em" xmlns="http://www.w3.org/2000/svg"><path d="M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1
c-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,
-36,557 l0,4284c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,
949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9
c0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,
-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189
l0,-4292c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,
-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.6501em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.18em;"><span style="top:-6.18em;"><span class="pstrut" style="height:4.98em;"></span><span class="mord"><span class="mord"><span class="mord mathit">alts</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.95em;"><span style="top:-4.95em;"><span class="pstrut" style="height:7.4em;"></span><span style="width:0.875em;height:5.400em;"><svg height="5.400em" viewbox="0 0 875 5400" width="0.875em" xmlns="http://www.w3.org/2000/svg"><path d="M863,9c0,-2,-2,-5,-6,-9c0,0,-17,0,-17,0c-12.7,0,-19.3,0.3,-20,1
c-5.3,5.3,-10.3,11,-15,17c-242.7,294.7,-395.3,682,-458,1162c-21.3,163.3,-33.3,349,
-36,557 l0,1884c0.2,6,0,26,0,60c2,159.3,10,310.7,24,454c53.3,528,210,
949.7,470,1265c4.7,6,9.7,11.7,15,17c0.7,0.7,7,1,19,1c0,0,18,0,18,0c4,-4,6,-7,6,-9
c0,-2.7,-3.3,-8.7,-10,-18c-135.3,-192.7,-235.5,-414.3,-300.5,-665c-65,-250.7,-102.5,
-544.7,-112.5,-882c-2,-104,-3,-167,-3,-189
l0,-1892c0,-162.7,5.7,-314,17,-454c20.7,-272,63.7,-513,129,-723c65.3,
-210,155.3,-396.3,270,-559c6.7,-9.3,10,-15.3,10,-18z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.45em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.98em;"><span style="top:-5.8275em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mpunct">;</span></span></span></span><span style="top:-3.9675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord">⋮</span><span class="mord rule" style="border-right-width:0em;border-top-width:1.5em;bottom:0em;"></span></span></span></span><span style="top:-2.7675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">vs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mpunct">;</span></span></span></span><span style="top:-1.5675em;"><span class="pstrut" style="height:3.6875em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.48em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.95em;"><span style="top:-4.95em;"><span class="pstrut" style="height:7.4em;"></span><span style="width:0.875em;height:5.400em;"><svg height="5.400em" viewbox="0 0 875 5400" width="0.875em" xmlns="http://www.w3.org/2000/svg"><path d="M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,
63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5
c11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0,1809
c-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664
c-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11
c0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17
c242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558
l0,-1944c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,
-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.45em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∀1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">n</span><span class="mpunct">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.86em;"><span class="pstrut" style="height:4.98em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">ρ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">ρ</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\n</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ws</span></span><span class="mclose">⟩]</span></span></span><span style="top:-1.66em;"><span class="pstrut" style="height:4.98em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathit">vs</span></span><span class="mord"> </span><span class="mord cjk_fallback">は</span><span class="mord"> ∣</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">ws</span></span><span class="mord">∣ </span><span class="mord cjk_fallback">を満たす</span><span class="mord"> fresh </span><span class="mord cjk_fallback">な変数列</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.68em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.1499em;"><span style="top:-6.1499em;"><span class="pstrut" style="height:9.8em;"></span><span style="width:0.875em;height:7.800em;"><svg height="7.800em" viewbox="0 0 875 7800" width="0.875em" xmlns="http://www.w3.org/2000/svg"><path d="M76,0c-16.7,0,-25,3,-25,9c0,2,2,6.3,6,13c21.3,28.7,42.3,60.3,
63,95c96.7,156.7,172.8,332.5,228.5,527.5c55.7,195,92.8,416.5,111.5,664.5
c11.3,139.3,17,290.7,17,454c0,28,1.7,43,3.3,45l0,4209
c-3,4,-3.3,16.7,-3.3,38c0,162,-5.7,313.7,-17,455c-18.7,248,-55.8,469.3,-111.5,664
c-55.7,194.7,-131.8,370.3,-228.5,527c-20.7,34.7,-41.7,66.3,-63,95c-2,3.3,-4,7,-6,11
c0,7.3,5.7,11,17,11c0,0,11,0,11,0c9.3,0,14.3,-0.3,15,-1c5.3,-5.3,10.3,-11,15,-17
c242.7,-294.7,395.3,-681.7,458,-1161c21.3,-164.7,33.3,-350.7,36,-558
l0,-4344c-2,-159.3,-10,-310.7,-24,-454c-53.3,-528,-210,-949.7,
-470,-1265c-4.7,-6,-9.7,-11.7,-15,-17c-0.7,-0.7,-6.7,-1,-18,-1z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.6501em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.28em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">束縛のないデフォルトケースと同じように,コンストラクタにパターンマッチするものがなくて,束縛が必要なデフォルトケースでの継続があった場合,その継続に復帰する.ただ,結果を束縛する必要があるので,コンストラクタ適用に相当するクロージャを生成して,それを束縛変数に結びつける.</p>
</dd>
<dt>更新スタックからの復帰</dt>
<dd><div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="center" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mi>c</mi><mtext> </mtext><mrow><mi>w</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">⟨</mo><msub><mrow><mi>a</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mrow><mi>r</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mi>a</mi><mi>u</mi></msub><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><mi>h</mi><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mi>c</mi><mtext> </mtext><mrow><mi>w</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><msub><mrow><mi>a</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><msub><mrow><mi>r</mi><mi>s</mi></mrow><mi>u</mi></msub><mo separator="true">,</mo><mrow><mi>u</mi><mi>s</mi></mrow><mo separator="true">,</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">(</mo><msup><mi>h</mi><mo lspace="0em" mathvariant="normal" rspace="0em">′</mo></msup><mo>=</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>a</mi><mi>u</mi></msub><mo>↦</mo><mo stretchy="false">⟨</mo><mrow><mi>v</mi><mi>s</mi></mrow><mo><mtext mathvariant="monospace">\n</mtext></mo><mo stretchy="false">{</mo><mo stretchy="false">}</mo><mo><mtext mathvariant="monospace">-></mtext></mo><mi>c</mi><mtext> </mtext><mrow><mi>v</mi><mi>s</mi></mrow><mo separator="true">,</mo><mrow><mi>w</mi><mi>s</mi></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mstyle displaystyle="false" scriptlevel="0"><mrow><mi>v</mi><mi>s</mi></mrow></mstyle><mtext> は </mtext><mstyle displaystyle="false" scriptlevel="0"><mi mathvariant="normal">∣</mi><mrow><mi>v</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi><mo>=</mo><mi mathvariant="normal">∣</mi><mrow><mi>w</mi><mi>s</mi></mrow><mi mathvariant="normal">∣</mi></mstyle><mtext> を満たす fresh な変数列</mtext></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{c}
\langle\mathbf{ReturnCon}\,c\,\mathit{ws}\rangle(
[],
[],
\langle \mathit{as}_u, \mathit{rs}_u, a_u\rangle\mathbin{:}\mathit{us},
h,
\sigma
)
\Rightarrow
\langle\mathbf{ReturnCon}\,c\,\mathit{ws}\rangle(
\mathit{as}_u,
\mathit{rs}_u,
\mathit{us},
h',
\sigma
) \\
(h' = h[a_u \mapsto \langle \mathit{vs}\mathrel{\text{\tt \textbackslash n}}\{\}\mathrel{\text{\tt ->}}c\,\mathit{vs}, \mathit{ws}\rangle],
\text{\(\mathit{vs}\) は \(|\mathit{vs}| = |\mathit{ws}|\) を満たす fresh な変数列}
)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ws</span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord"><span class="mord mathit">as</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">rs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ws</span></span><span class="mclose">⟩</span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathit">as</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathit">rs</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">us</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">u</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">\n</span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">{</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord text"><span class="mord"><span class="mord mathtt">-></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">vs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathit">ws</span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathit">vs</span></span><span class="mord"> </span><span class="mord cjk_fallback">は</span><span class="mord"> ∣</span><span class="mord"><span class="mord mathit">vs</span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathit">ws</span></span><span class="mord">∣ </span><span class="mord cjk_fallback">を満たす</span><span class="mord"> fresh </span><span class="mord cjk_fallback">な変数列</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p class="last">そもそも返り値スタックを使い切ってしまった場合,更新スタックに要素があるなら,それはサンクを評価した結果出てきた評価値ということなので,サンクのあった部分に評価後の結果を表すクロージャを挿入して,元の評価に戻る.</p>
</dd>
</dl>
<p><span class="math inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><annotation encoding="application/x-tex">\mathbf{ReturnInt}</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord mathbf">ReturnInt</span></span></span></span></span></span> の場合,デフォルトケースでの束縛時にヒープ割り当てを行わないで直接整数を束縛変数に結びつけるぐらいの違いしかない.</p>
</div>
<div class="section" id="auto-id-14">
<h3>遷移例<a class="headerlink" href="#auto-id-14" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>では,意味論に則って,実際に STG のプログラムを動かしてみる.以下のプログラムを動かしてみる:</p>
<pre class="literal-block">
main = {} \u {} ->
let nil = {} \n {} -> Nil {}
mapid = {} \u {} -> map1 {id}
in case 1# of
v ->
let l = {v, nil} \n {} -> Cons {v, nil}
in mapid {l}
id = {} \n {x} -> x {}
map1 = {} \n {f, xs} ->
letrec mf = {f, mf} \n {ys} ->
case ys {} of
Nil {} -> Nil {}
Cons {z, zs} ->
let fz = {f, z} \u {} -> f {z}
mfzs = {mf, zs} \u {} -> mf {zs}
in Cons {fz, mfzs}
in mf {xs}
</pre>
<p>このプログラムを意味論に沿って動かすと,次の動作をする:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">main</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext></mrow><mo stretchy="false">)</mo><mtext> </mtext><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo>=</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">main</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">id</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">map1</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">let</mtext><mtext> </mtext><mtext mathvariant="monospace">nil</mtext><mtext> </mtext><mtext mathvariant="monospace">=</mtext></mrow><mo>⋯</mo><mtext> </mtext><mo stretchy="false">)</mo><mtext> </mtext><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">case</mtext><mtext> </mtext><mtext mathvariant="monospace">1#</mtext><mtext> </mtext><mtext mathvariant="monospace">of</mtext></mrow><mo>⋯</mo><mtext> </mtext><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">nil</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mapid</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo lspace="0.22em" rspace="0.22em">:</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">1#</mtext><mtext> </mtext><mo stretchy="false">[</mo><mo>⋯</mo><mtext> </mtext><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mrow><mtext mathvariant="monospace">v</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">nil</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mapid</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mn>1</mn><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mrow><mtext mathvariant="monospace">v</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">nil</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mapid</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">let</mtext><mtext> </mtext><mtext mathvariant="monospace">l</mtext><mtext> </mtext><mtext mathvariant="monospace">=</mtext><mtext> </mtext></mrow><mo>⋯</mo><mtext> </mtext><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">nil</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mapid</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">v</mtext><mo>↦</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mn>1</mn></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">mapid</mtext><mtext> </mtext><mtext mathvariant="monospace">{l}</mtext></mrow><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">nil</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mapid</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">v</mtext><mo>↦</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mn>1</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">l</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">map1</mtext><mtext> </mtext><mtext mathvariant="monospace">{id}</mtext></mrow><mo stretchy="false">)</mo><mtext> </mtext><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo stretchy="false">⟩</mo><mo separator="true">,</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo separator="true">,</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo stretchy="false">⟨</mo><mrow><mtext mathvariant="monospace">{f}</mtext><mtext> </mtext><mtext mathvariant="monospace">\n</mtext><mtext> </mtext><mtext mathvariant="monospace">{xs}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo><mtext> </mtext><mo separator="true">,</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">letrec</mtext><mtext> </mtext><mtext mathvariant="monospace">mf</mtext><mtext> </mtext><mtext mathvariant="monospace">=</mtext><mtext> </mtext></mrow><mo>⋯</mo><mtext> </mtext><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">xs</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">mf</mtext><mtext> </mtext><mtext mathvariant="monospace">{xs}</mtext></mrow><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">xs</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">case</mtext><mtext> </mtext><mtext mathvariant="monospace">ys</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext><mtext> </mtext><mtext mathvariant="monospace">of</mtext></mrow><mo>⋯</mo><mtext> </mtext><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">ys</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mrow><mtext mathvariant="monospace">ys</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext></mrow><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">ys</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mrow><mo fence="true">⟨</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">Nil</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mtext mathvariant="monospace">{z,</mtext><mtext> </mtext><mtext mathvariant="monospace">zs}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">ys</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo fence="true">⟩</mo></mrow><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mrow><mo fence="true">⟨</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">Nil</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mtext mathvariant="monospace">{z,</mtext><mtext> </mtext><mtext mathvariant="monospace">zs}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">ys</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo fence="true">⟩</mo></mrow><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mtext mathvariant="monospace">{v,</mtext><mtext> </mtext><mtext mathvariant="monospace">nil}</mtext></mrow><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">v</mtext><mo>↦</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mn>1</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">nil</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mrow><mo fence="true">⟨</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">Nil</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mtext mathvariant="monospace">{z,</mtext><mtext> </mtext><mtext mathvariant="monospace">zs}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">ys</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo fence="true">⟩</mo></mrow><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mn>1</mn><mo separator="true">,</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mrow><mo fence="true">⟨</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">Nil</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mrow><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mtext mathvariant="monospace">{z,</mtext><mtext> </mtext><mtext mathvariant="monospace">zs}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext></mrow><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">ys</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo fence="true">⟩</mo></mrow><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">let</mtext><mtext> </mtext><mtext mathvariant="monospace">fz</mtext><mtext> </mtext><mtext mathvariant="monospace">=</mtext></mrow><mo>⋯</mo><mtext> </mtext><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">ys</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">z</mtext><mo>↦</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mn>1</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">zs</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">E</mi><mi mathvariant="bold">v</mi><mi mathvariant="bold">a</mi><mi mathvariant="bold">l</mi></mrow><mtext> </mtext><mo stretchy="false">(</mo><mrow><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mtext mathvariant="monospace">{fz,</mtext><mtext> </mtext><mtext mathvariant="monospace">mfzs}</mtext></mrow><mo stretchy="false">)</mo><mtext> </mtext><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">f</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mf</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">ys</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">z</mtext><mo>↦</mo><mrow><mi mathvariant="bold">I</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">t</mi></mrow><mtext> </mtext><mn>1</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">zs</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">fz</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">fz</mtext></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mtext mathvariant="monospace">mfzs</mtext><mo>↦</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mfzs</mtext></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">fz</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mfzs</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">fz</mtext></msub><mo separator="true">,</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mfzs</mtext></msub><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">⟨</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo stretchy="false">⟩</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">fz</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mfzs</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><mo>⇒</mo><mo stretchy="false">⟨</mo><mrow><mi mathvariant="bold">R</mi><mi mathvariant="bold">e</mi><mi mathvariant="bold">t</mi><mi mathvariant="bold">u</mi><mi mathvariant="bold">r</mi><mi mathvariant="bold">n</mi><mi mathvariant="bold">C</mi><mi mathvariant="bold">o</mi><mi mathvariant="bold">n</mi></mrow><mtext> </mtext><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">fz</mtext></msub><mo separator="true">,</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mfzs</mtext></msub><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo><mo stretchy="false">(</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mo stretchy="false">[</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mrow><mo fence="true">[</mo><mtable columnalign="left" columnspacing="1em" rowspacing="0.16em"><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">id</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">map1</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">nil</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">l</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mapid</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mf</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">fz</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">mfzs</mtext></msub><mo>↦</mo><mo>⋯</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle displaystyle="false" scriptlevel="0"><mrow><msub><mi>a</mi><mtext mathvariant="monospace">main</mtext></msub><mo>↦</mo><mo stretchy="false">⟨</mo><mrow><mtext mathvariant="monospace">{fz,</mtext><mtext> </mtext><mtext mathvariant="monospace">mfzs}</mtext><mtext> </mtext><mtext mathvariant="monospace">\n</mtext><mtext> </mtext><mtext mathvariant="monospace">{}</mtext><mtext> </mtext><mtext mathvariant="monospace">-></mtext><mtext> </mtext><mtext mathvariant="monospace">Cons</mtext><mtext> </mtext><mtext mathvariant="monospace">{fz,</mtext><mtext> </mtext><mtext mathvariant="monospace">mfzs}</mtext></mrow><mo separator="true">,</mo><mo stretchy="false">[</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">fz</mtext></msub><mo separator="true">,</mo><mrow><mi mathvariant="bold">A</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">d</mi><mi mathvariant="bold">r</mi></mrow><mtext> </mtext><msub><mi>a</mi><mtext mathvariant="monospace">mfzs</mtext></msub><mo stretchy="false">]</mo><mo stretchy="false">⟩</mo></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo separator="true">,</mo><mi>σ</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">
\begin{array}{l}
\langle \mathbf{Eval}\,(\text{\tt main \{\}})\,[]\rangle(
[],
[],
[],
\left[\begin{array}{l}
a_{\text{\tt main}} \mapsto \cdots \\
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots
\end{array}\right],
\sigma = \left[\begin{array}{l}
\text{\tt main} \mapsto \mathbf{Addr}\,a_{\text{\tt main}} \\
\text{\tt id} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt map1} \mapsto \mathbf{Addr}\,a_{\text{\tt map1}}
\end{array}\right]
) \\
\Rightarrow
\langle \mathbf{Enter}\,a_{\text{\tt main}}\rangle(
[],
[],
[],
\left[\begin{array}{l}
a_{\text{\tt main}} \mapsto \cdots \\
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt let nil =} \cdots)\,[]\rangle(
[],
[],
\langle [], [], a_{\text{\tt main}}\rangle\mathbin{:}[],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt case 1\# of} \cdots)\,\left[\begin{array}{l}
\text{\tt nil} \mapsto \mathbf{Addr}\,a_{\text{\tt nil}} \\
\text{\tt mapid} \mapsto \mathbf{Addr}\,a_{\text{\tt mapid}}
\end{array}\right]\rangle(
[],
[],
\langle [], [], a_{\text{\tt main}}\rangle\mathbin{:}[],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,\text{\tt 1\#}\,[\cdots]\rangle(
[],
[\langle\text{\tt v -> }\cdots, \left[\begin{array}{l}
\text{\tt nil} \mapsto \mathbf{Addr}\,a_{\text{\tt nil}} \\
\text{\tt mapid} \mapsto \mathbf{Addr}\,a_{\text{\tt mapid}}
\end{array}\right]\rangle],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{ReturnInt}\,1\rangle(
[],
[\langle\text{\tt v -> }\cdots, \left[\begin{array}{l}
\text{\tt nil} \mapsto \mathbf{Addr}\,a_{\text{\tt nil}} \\
\text{\tt mapid} \mapsto \mathbf{Addr}\,a_{\text{\tt mapid}}
\end{array}\right]\rangle],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt let l = }\cdots)\,\left[\begin{array}{l}
\text{\tt nil} \mapsto \mathbf{Addr}\,a_{\text{\tt nil}} \\
\text{\tt mapid} \mapsto \mathbf{Addr}\,a_{\text{\tt mapid}} \\
\text{\tt v} \mapsto \mathbf{Int}\,1
\end{array}\right]\rangle(
[],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt mapid \{l\}})\,\left[\begin{array}{l}
\text{\tt nil} \mapsto \mathbf{Addr}\,a_{\text{\tt nil}} \\
\text{\tt mapid} \mapsto \mathbf{Addr}\,a_{\text{\tt mapid}} \\
\text{\tt v} \mapsto \mathbf{Int}\,1 \\
\text{\tt l} \mapsto \mathbf{Addr}\,a_{\text{\tt l}}
\end{array}\right]\rangle(
[],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Enter}\,a_{\text{\tt mapid}}\rangle(
[\mathbf{Addr}\,a_{\text{\tt l}}],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt map1 \{id\}})\,[]\rangle(
[],
[],
[
\langle [\mathbf{Addr}\,a_{\text{\tt l}}], [], a_{\text{\tt mapid}}\rangle,
\langle [], [], a_{\text{\tt main}}\rangle
],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Enter}\,a_{\text{\tt map1}}\rangle(
[\mathbf{Addr}\,a_{\text{\tt id}}],
[],
[
\langle [\mathbf{Addr}\,a_{\text{\tt l}}], [], a_{\text{\tt mapid}}\rangle,
\langle [], [], a_{\text{\tt main}}\rangle
],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Enter}\,a_{\text{\tt map1}}\rangle(
[\mathbf{Addr}\,a_{\text{\tt id}}, \mathbf{Addr}\,a_{\text{\tt l}}],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \langle \text{\tt \{f\} \textbackslash n \{xs\} -> } \cdots, [\mathbf{Addr}\,a_{\text{\tt id}}]\rangle
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt letrec mf = }\cdots)\,\left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt xs} \mapsto \mathbf{Addr}\,a_{\text{\tt l}}
\end{array}\right]\rangle(
[],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt mf \{xs\}})\,\left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt xs} \mapsto \mathbf{Addr}\,a_{\text{\tt l}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}}
\end{array}\right]\rangle(
[],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Enter}\,a_{\text{\tt mf}}\rangle(
[\mathbf{Addr}\,a_{\text{\tt l}}],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt case ys \{\} of} \cdots)\,\left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}} \\
\text{\tt ys} \mapsto \mathbf{Addr}\,a_{\text{\tt l}}
\end{array}\right]\rangle(
[],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,\text{\tt ys \{\}}\,\left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}} \\
\text{\tt ys} \mapsto \mathbf{Addr}\,a_{\text{\tt l}}
\end{array}\right]\rangle(
[],
[\left\langle \begin{array}{l}
\text{\tt Nil \{\} -> } \cdots \\
\text{\tt Cons \{z, zs\} -> } \cdots
\end{array}, \left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}} \\
\text{\tt ys} \mapsto \mathbf{Addr}\,a_{\text{\tt l}}
\end{array}\right]\right\rangle],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Enter}\,a_{\text{\tt l}}\rangle(
[],
[\left\langle \begin{array}{l}
\text{\tt Nil \{\} -> } \cdots \\
\text{\tt Cons \{z, zs\} -> } \cdots
\end{array}, \left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}} \\
\text{\tt ys} \mapsto \mathbf{Addr}\,a_{\text{\tt l}}
\end{array}\right]\right\rangle],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt Cons \{v, nil\}})\,\left[\begin{array}{l}
\text{\tt v} \mapsto \mathbf{Int}\,1 \\
\text{\tt nil} \mapsto \mathbf{Addr}\,a_{\text{\tt nil}}
\end{array}\right]\rangle(
[],
[\left\langle \begin{array}{l}
\text{\tt Nil \{\} -> } \cdots \\
\text{\tt Cons \{z, zs\} -> } \cdots
\end{array}, \left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}} \\
\text{\tt ys} \mapsto \mathbf{Addr}\,a_{\text{\tt l}}
\end{array}\right]\right\rangle],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{ReturnCon}\,\text{\tt Cons}\,[\mathbf{Int}\,1, \mathbf{Addr}\,a_{\text{\tt nil}}]\rangle(
[],
[\left\langle \begin{array}{l}
\text{\tt Nil \{\} -> } \cdots \\
\text{\tt Cons \{z, zs\} -> } \cdots
\end{array}, \left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}} \\
\text{\tt ys} \mapsto \mathbf{Addr}\,a_{\text{\tt l}}
\end{array}\right]\right\rangle],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt let fz =} \cdots)\,\left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}} \\
\text{\tt ys} \mapsto \mathbf{Addr}\,a_{\text{\tt l}} \\
\text{\tt z} \mapsto \mathbf{Int}\,1 \\
\text{\tt zs} \mapsto \mathbf{Addr}\,a_{\text{\tt nil}}
\end{array}\right]\rangle(
[],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{Eval}\,(\text{\tt Cons \{fz, mfzs\}})\,\left[\begin{array}{l}
\text{\tt f} \mapsto \mathbf{Addr}\,a_{\text{\tt id}} \\
\text{\tt mf} \mapsto \mathbf{Addr}\,a_{\text{\tt mf}} \\
\text{\tt ys} \mapsto \mathbf{Addr}\,a_{\text{\tt l}} \\
\text{\tt z} \mapsto \mathbf{Int}\,1 \\
\text{\tt zs} \mapsto \mathbf{Addr}\,a_{\text{\tt nil}} \\
\text{\tt fz} \mapsto \mathbf{Addr}\,a_{\text{\tt fz}} \\
\text{\tt mfzs} \mapsto \mathbf{Addr}\,a_{\text{\tt mfzs}}
\end{array}\right]\rangle(
[],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots \\
a_{\text{\tt fz}} \mapsto \cdots \\
a_{\text{\tt mfzs}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{ReturnCon}\,\text{\tt Cons}\,[\mathbf{Addr}\,a_{\text{\tt fz}}, \mathbf{Addr}\,a_{\text{\tt mfzs}}]\rangle(
[],
[],
[\langle [], [], a_{\text{\tt main}}\rangle],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots \\
a_{\text{\tt fz}} \mapsto \cdots \\
a_{\text{\tt mfzs}} \mapsto \cdots
\end{array}\right],
\sigma
) \\
\Rightarrow
\langle \mathbf{ReturnCon}\,\text{\tt Cons}\,[\mathbf{Addr}\,a_{\text{\tt fz}}, \mathbf{Addr}\,a_{\text{\tt mfzs}}]\rangle(
[],
[],
[],
\left[\begin{array}{l}
a_{\text{\tt id}} \mapsto \cdots \\
a_{\text{\tt map1}} \mapsto \cdots \\
a_{\text{\tt nil}} \mapsto \cdots \\
a_{\text{\tt l}} \mapsto \cdots \\
a_{\text{\tt mapid}} \mapsto \cdots \\
a_{\text{\tt mf}} \mapsto \cdots \\
a_{\text{\tt fz}} \mapsto \cdots \\
a_{\text{\tt mfzs}} \mapsto \cdots \\
a_{\text{\tt main}} \mapsto \langle \text{\tt \{fz, mfzs\} \textbackslash n \{\} -> Cons \{fz, mfzs\}} , [\mathbf{Addr}\,a_{\text{\tt fz}}, \mathbf{Addr}\,a_{\text{\tt mfzs}}]\rangle
\end{array}\right],
\sigma
)
\end{array}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:150.001em;vertical-align:-74.7505em;"></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:75.2505em;"><span style="top:-80.8505em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">main {}</span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">main</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">id</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">map1</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-77.2505em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-74.2505em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">let nil =</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-70.6504em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">case 1# of</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">nil</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mapid</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mrel">:</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v1200 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v1200 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-65.8504em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">1#</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">]⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨</span><span class="mord text"><span class="mord"><span class="mord mathtt">v -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">nil</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mapid</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v1200 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v1200 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-61.0504em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnInt</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨</span><span class="mord text"><span class="mord"><span class="mord mathtt">v -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">nil</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mapid</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v1200 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v1200 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-56.2504em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">let l = </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">nil</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mapid</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">v</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v1200 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v1200 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-50.8503em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">mapid {l}</span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v1200 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">nil</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mapid</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">v</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">l</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v1200 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v2400 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v2400 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-44.8503em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v2400 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v2400 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-39.4502em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">map1 {id}</span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v1200 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v1200 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-34.6502em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v1200 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg height="4.800em" viewbox="0 0 667 4800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v1200 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v1200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-29.2502em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v2400 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord text"><span class="mord"><span class="mord mathtt">{f} \n {xs} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]⟩</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v2400 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-23.2501em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">letrec mf = </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">xs</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v2400 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v2400 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-16.6501em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">mf {xs}</span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">xs</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v3600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v3600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-9.4501em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v3600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v3600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">case ys {} of</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">ys</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v3600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v3600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:4.95em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">ys {}</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">ys</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">⟨</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">Nil {} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">Cons {z, zs} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">ys</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size4">⟩</span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v3600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v3600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:12.1501em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Enter</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">⟨</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">Nil {} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">Cons {z, zs} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">ys</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size4">⟩</span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v3600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v3600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:19.3501em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">Cons {v, nil}</span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">v</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">nil</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">⟨</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">Nil {} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">Cons {z, zs} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">ys</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size4">⟩</span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v3600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v3600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:26.5502em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">Cons</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">⟨</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">Nil {} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">Cons {z, zs} -> </span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">ys</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg height="3.600em" viewbox="0 0 667 3600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v0 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size4">⟩</span></span></span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v3600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v3600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:33.7502em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">let fz =</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v2400 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">ys</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">z</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">zs</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg height="6.000em" viewbox="0 0 667 6000" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v2400 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v2400 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v3600 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.8499em;"><span class="pstrut" style="height:9.2em;"></span><span style="width:0.667em;height:7.200em;"><svg height="7.200em" viewbox="0 0 667 7200" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v3600 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v3600 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:42.1503em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">Eval</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord text"><span class="mord"><span class="mord mathtt">Cons {fz, mfzs}</span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.4499em;"><span style="top:-6.4499em;"><span class="pstrut" style="height:10.4em;"></span><span style="width:0.667em;height:8.400em;"><svg height="8.400em" viewbox="0 0 667 8400" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v4800 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v4800 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.9501em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.45em;"><span style="top:-6.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">f</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mf</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">ys</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">z</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Int</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">zs</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">fz</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">fz</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:0.59em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord"><span class="mord mathtt">mfzs</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mfzs</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.4499em;"><span style="top:-6.4499em;"><span class="pstrut" style="height:10.4em;"></span><span style="width:0.667em;height:8.400em;"><svg height="8.400em" viewbox="0 0 667 8400" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v4800 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v4800 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:3.9501em;"><span></span></span></span></span></span></span></span><span class="mclose">⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.0499em;"><span style="top:-7.0499em;"><span class="pstrut" style="height:11.6em;"></span><span style="width:0.667em;height:9.600em;"><svg height="9.600em" viewbox="0 0 667 9600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v6000 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v6000 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.5501em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.05em;"><span style="top:-7.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">fz</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:1.19em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mfzs</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.0499em;"><span style="top:-7.0499em;"><span class="pstrut" style="height:11.6em;"></span><span style="width:0.667em;height:9.600em;"><svg height="9.600em" viewbox="0 0 667 9600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v6000 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v6000 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.5501em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:51.7504em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">Cons</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">fz</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mfzs</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[⟨[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">⟩]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.0499em;"><span style="top:-7.0499em;"><span class="pstrut" style="height:11.6em;"></span><span style="width:0.667em;height:9.600em;"><svg height="9.600em" viewbox="0 0 667 9600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v6000 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v6000 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.5501em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.05em;"><span style="top:-7.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-6.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">fz</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:1.19em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mfzs</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.0499em;"><span style="top:-7.0499em;"><span class="pstrut" style="height:11.6em;"></span><span style="width:0.667em;height:9.600em;"><svg height="9.600em" viewbox="0 0 667 9600" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v6000 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v6000 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:4.5501em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span><span style="top:61.9504em;"><span class="pstrut" style="height:7.65em;"></span><span class="mord"><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord"><span class="mord mathbf">ReturnCon</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord"><span class="mord mathtt">Cons</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">fz</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mfzs</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]⟩</span><span class="mopen">([</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.6499em;"><span style="top:-7.6499em;"><span class="pstrut" style="height:12.8em;"></span><span style="width:0.667em;height:10.800em;"><svg height="10.800em" viewbox="0 0 667 10800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M403 1759 V84 H666 V0 H319 V1759 v7200 v1759 h347 v-84
H403z M403 1759 V0 H319 V1759 v7200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:5.1501em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.65em;"><span style="top:-7.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">id</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-6.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">map1</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">nil</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">l</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mapid</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3056em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mf</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">fz</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:0.59em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mfzs</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner">⋯</span></span></span><span style="top:1.79em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">main</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">⟨</span><span class="mord text"><span class="mord"><span class="mord mathtt">{fz, mfzs} \n {} -> Cons {fz, mfzs}</span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">fz</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathbf">Addr</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2778em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight"><span class="mord mathtt mtight">mfzs</span></span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]⟩</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:5.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.6499em;"><span style="top:-7.6499em;"><span class="pstrut" style="height:12.8em;"></span><span style="width:0.667em;height:10.800em;"><svg height="10.800em" viewbox="0 0 667 10800" width="0.667em" xmlns="http://www.w3.org/2000/svg"><path d="M347 1759 V0 H0 V84 H263 V1759 v7200 v1759 H0 v84 H347z
M347 1759 V0 H263 V1759 v7200 v1759 h84z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:5.1501em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mclose">)</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:74.7505em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span></span></span></span></span></div>
<p>ヒープはサンクを潰す時ぐらいしか整理してないので,参照がなくなったものは随時消す GC を実装すれば簡単に実行マシンは作れそう.</p>
</div>
</div>
<div class="section" id="auto-id-15">
<h2>まとめ<a class="headerlink" href="#auto-id-15" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まとめたかったのは主に, Part III の具体的な実装の話だったんだが力尽きた.てことで今日はこれで.続きは書くかもしれないし,書かないかもしれない.</p>
<p>機会があればもうちょっと正確を期して,どっかに上げるかもしれない.</p>
<table class="docutils footnote" frame="void" id="spineless-is-still" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td>spineless は僕の認識が正しければ生きてるはずだが,G-machine の実装では spineless は普通だったみたいな話があり, spineless もそこまで気にする用語ではないって事ですね.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="shared-term-graph" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td>なお,元々 shared term graph という二重の意味が込められてたっぽい: <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/stgSyn/StgSyn.hs#L4">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/stgSyn/StgSyn.hs#L4</a> .こっちの言い方は今でも通用しそうだが, STG machine はこっちの言い方だと shared term graph machine という感じになりそうで, reduction が抜けてるのはなんかあれですね.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="haskell-optimizing-community" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[3]</a></td><td>Haskell 界には, Haskell 最適化委員会なる組織があるらしく,その人たちは Haskell プログラムでもそういうのを見通す力を持ってるらしい.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="all-variables-were-heap-allocated" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-6">[4]</a></td><td>厳密には全てがヒープ割り当てされてるとは限らなくて, case での束縛はスタックに積まれるみたいなこともある.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="example-by-paper" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[5]</a></td><td>例は論文中から持ってきたもの.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/haskell-old-stg-syntax.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/haskell-old-stg-syntax.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>unified 形式パッチの文法について2019-04-18T13:00:59+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-18:/blog/posts/2019/04/about-unified-diff-style/<p>パッチファイルの形式にはいくつかあるわけだが, <cite>git</cite> の <cite>diff</cite> で使われている形式について,ちょっと調べたのでそのメ …</p><p>パッチファイルの形式にはいくつかあるわけだが, <cite>git</cite> の <cite>diff</cite> で使われている形式について,ちょっと調べたのでそのメモ.</p>
<div class="section" id="diff">
<h2>diff 形式<a class="headerlink" href="#diff" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>diff コマンドが吐き出す形式は色々ある.主に以下のものがあるらしい <a class="footnote-reference" href="#diffutils-manual-output-formats" id="auto-id-1">[1]</a> :</p>
<dl class="docutils">
<dt>通常の形式</dt>
<dd>差分部分だけを表示する, diff のデフォルトの表示形式</dd>
<dt>コンテキスト形式</dt>
<dd>差分部分周辺も含めて,どういう風に変わったかが分かるようになっている,表示形式</dd>
<dt>side by side 形式</dt>
<dd>2列で差分を表示する形式</dd>
<dt>スクリプト形式</dt>
<dd>ed コマンドなどでそのまま実行すれば,差分を適用できる形式</dd>
<dt>if-then-else 形式</dt>
<dd>CPP のマクロで,両方を切り替えられるようにした形式.差分部分を <tt class="docutils literal">#ifdef</tt> で囲って出してくれ,指定したマクロ変数を定義すると古いのに切り替えられる.</dd>
</dl>
<p>色々あるけど,パッチを送信する際よく使用されるのは,プレーンテキストでも差分を確認しやすいコンテキスト形式だ.コンテキスト形式の中でもいくつか種類があって,主に以下のものがある <a class="footnote-reference" href="#diffutils-manual-contexts" id="auto-id-2">[2]</a> :</p>
<dl class="docutils">
<dt>(狭義の) コンテキスト形式</dt>
<dd>patch コマンドの標準形式っぽい.追加 / 削除に加えて,変更を表す表記がある.</dd>
<dt>unified 形式</dt>
<dd><tt class="docutils literal">git diff</tt> で使われている形式.追加 / 削除しかないやつ.</dd>
</dl>
<p>他にもオプションを指定することで表示を変えられるが,主要なのは上の 2 通りだと考えていいと思う.今回は, unified 形式のみを見ていく.</p>
</div>
<div class="section" id="auto-id-3">
<h2>unified 形式の構文<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>コンテキスト形式の差分は,ヘッダ情報とハンク (hunk) と呼ばれる差分を表すコードブロックの集まりから為っている.ヘッダ情報は,以下の形式になる:</p>
<pre class="literal-block">
--- from-file from-file-modification-time
+++ to-file to-file-modification-time
</pre>
<p>まあ書いてある通り.例えば,以下のような感じ:</p>
<pre class="literal-block">
--- dir/test.c.orig 2019-04-15 16:48:32.000000000 +0900
+++ dir/test.c 2019-04-08 12:40:22.000000000 +0900
</pre>
<p>なお, <tt class="docutils literal">diffutils</tt> のマニュアルには書いてないんだが, <tt class="docutils literal">git diff</tt> は変更時間を出さないので,変更時間は書かなくてもいいのかもしれない.ハンクは以下の形式になる:</p>
<pre class="literal-block">
@@ from-file-line-numbers to-file-line-numbers @@
line-from-either-file
line-from-either-file
...
</pre>
<p><tt class="docutils literal"><span class="pre">file-line-numbers</span></tt> は, <tt class="docutils literal">start, count</tt> の形式をしている. <tt class="docutils literal">start</tt> は開始位置, <tt class="docutils literal">count</tt> は開始行からの表示行数になる.それぞれの行は,</p>
<ul class="simple">
<li>特に変更がないところは空白 1 つ</li>
<li>追加した行は <tt class="docutils literal">+</tt></li>
<li>削除した行は <tt class="docutils literal">-</tt></li>
</ul>
<p>を先頭につける.例えば,以下のような感じ:</p>
<pre class="literal-block">
@@ -1,5 +1,5 @@
#include <stdio.h>
int main(void) {
- printf("Hello, World!\n");
+ puts("Hello, World!");
}
</pre>
<p>注意して欲しいのは,位置も行数も差分ではなく表示されている行から換算するってこと.上の例だと,差分があるのは4行目だけど <tt class="docutils literal">start</tt> は 1 で, <tt class="docutils literal">count</tt> も変更される前のファイルの表示されてる行数 5 になる.なお,この行数を間違えると,パッチコマンドでは以下のエラーが出る:</p>
<pre class="literal-block">
$ cat test.c.patch
--- test.c.orig 2019-04-18 21:45:33.000000000 +0900
+++ test.c 2019-04-18 21:45:07.000000000 +0900
@@ -1,4 +1,5 @@
#include <stdio.h>
int main(void) {
- printf("Hello, World!\n");
+ puts("Hello, World!");
}
$ patch test.c.orig < test.c.patch
patching file test.c.orig
patch: **** malformed patch at line 9: }
</pre>
<p>エラーメッセージは分かりにくいが, 9 行目の <tt class="docutils literal">}</tt> でエラーが出ているのは, <tt class="docutils literal"><span class="pre">from-file-line-numbers</span></tt> で 4 行のハンクだと言っているのに 5 行目があるじゃないかと怒っているんだと思う.なお,一行以下のハンクの場合,カウントの部分は書かなくていいらしい:</p>
<pre class="literal-block">
@@ -1 +1 @@
-aaa
+aaaa
</pre>
<p>それから空ハンクはそこでハンクが終了することを示すらしい.これは何処で使われてるんだろね.</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal">git diff</tt> で使われてるパッチ形式を調べた.これで手動でパッチ作成とかできそう.また一つ賢くなってしまった.</p>
<table class="docutils footnote" frame="void" id="diffutils-manual-output-formats" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td><a class="reference external" href="https://www.gnu.org/software/diffutils/manual/diffutils.html#Output-Formats">https://www.gnu.org/software/diffutils/manual/diffutils.html#Output-Formats</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="diffutils-manual-contexts" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td><a class="reference external" href="https://www.gnu.org/software/diffutils/manual/diffutils.html#Context">https://www.gnu.org/software/diffutils/manual/diffutils.html#Context</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/about-unified-diff-style.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/about-unified-diff-style.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>脚注のためのツールチップ追加2019-04-15T13:06:18+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-15:/blog/posts/2019/04/add-tooltip-for-footnote/<p>脚注をツールチップで見れるようにしたので,それについて.</p>
<div class="section" id="restructuredtext">
<h2>reStructuredText の脚注<a class="headerlink" href="#restructuredtext" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>reStructuredText では脚注が使える.これは,以下のように書け …</p></div><p>脚注をツールチップで見れるようにしたので,それについて.</p>
<div class="section" id="restructuredtext">
<h2>reStructuredText の脚注<a class="headerlink" href="#restructuredtext" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>reStructuredText では脚注が使える.これは,以下のように書けばいい:</p>
<pre class="literal-block">
some text[#footnote-ref]_ .
.. [#footnote-ref] some footnote content.
</pre>
<p>こうすると,自動でナンバリングが行われ,それぞれ脚注へのリンクと元の文書へのバックリンクが生成される.分かりづらいがバックリンクは,数字の部分に当てがわれ,それをクリックすることで戻れる.ただ,これをクリックするのがめんどかったので,ツールチップで表示してみることにした.</p>
</div>
<div class="section" id="tooltip-js">
<h2>Tooltip.js を使う<a class="headerlink" href="#tooltip-js" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ツールチップライブラリとして, Popper.js が提供する Tooltip.js を使うことにした. Popper.js は Bootstrap がツールチップ表示のために使っているツールチップ専用の位置調整ライブラリ. Tooltip.js は Popper.js を使ってツールチップを表示してくれるライブラリだ.まずは, npm でインストールする:</p>
<pre class="literal-block">
npm install -S tooltip.js
</pre>
<p>で,後は以下のようなことを書くだけ:</p>
<pre class="literal-block">
new Tooltip(document.getElementById('some-id'), {
placement: "bottom",
title: "<p>some content</p>",
html: true,
});
</pre>
<p>デフォルトでは HTML は使えなくてサニタイズがちゃんとされる.今回は HTML の内容を表示するようにしている.こうすると, <tt class="docutils literal"><span class="pre">#some-id</span></tt> の要素にホバーすると,下にツールチップが表示されるようになる.今回は脚注の内容を登録したいので, JavaScript で脚注の内容を持ってきてツールチップを登録していく,以下の簡単なコードを書いた:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span></pre></div></td><td class="code"><div><pre><span></span><span class="kd">let</span><span class="w"> </span><span class="nx">footnoteTitles</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{};</span>
<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="s2">"table.docutils.footnote"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">eid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s2">"id"</span><span class="p">);</span>
<span class="w"> </span><span class="nx">footnoteTitles</span><span class="p">[</span><span class="nx">eid</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="s2">"td:not(.label)"</span><span class="p">).</span><span class="nx">innerHTML</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">querySelectorAll</span><span class="p">(</span><span class="s2">"a.footnote-reference"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">eid</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s2">"id"</span><span class="p">);</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">reference</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">e</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s2">"href"</span><span class="p">).</span><span class="nx">substr</span><span class="p">(</span><span class="mf">1</span><span class="p">);</span>
<span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">tooltipContent</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">'div'</span><span class="p">);</span>
<span class="w"> </span><span class="nx">tooltipContent</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">'class'</span><span class="p">,</span><span class="w"> </span><span class="s1">'footnote-tooltip-content'</span><span class="p">);</span>
<span class="w"> </span><span class="nx">tooltipContent</span><span class="p">.</span><span class="nx">innerHTML</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">footnoteTitles</span><span class="p">[</span><span class="nx">reference</span><span class="p">];</span>
<span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Tooltip</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="nx">eid</span><span class="p">),</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">placement</span><span class="o">:</span><span class="w"> </span><span class="s2">"bottom"</span><span class="p">,</span>
<span class="w"> </span><span class="nx">title</span><span class="o">:</span><span class="w"> </span><span class="nx">tooltipContent</span><span class="p">,</span>
<span class="w"> </span><span class="nx">html</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w"> </span><span class="p">});</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>ただ,ツールチップ導入の際気をつけたいことがあって,スマフォなどのタッチデバイスだとホバーイベントによる表示は逆にユーザ体験が悪いので,無効にしておくのが良い.ってことまでは思って,そういや Bootstrap のツールチップとかスマフォで表示されないよな,どうやってんだろと思ってソースを見に行った.そうすると,こんなことをしてた <a class="footnote-reference" href="#bootstrap-touch-device-detection" id="auto-id-2">[1]</a>:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">// If this is a touch-enabled device we add extra</span>
<span class="c1">// empty mouseover listeners to the body's immediate children;</span>
<span class="c1">// only needed because of broken event delegation on iOS</span>
<span class="c1">// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="s1">'ontouchstart'</span><span class="w"> </span><span class="ow">in</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">).</span><span class="nx">children</span><span class="p">().</span><span class="nx">on</span><span class="p">(</span><span class="s1">'mouseover'</span><span class="p">,</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nx">$</span><span class="p">.</span><span class="nx">noop</span><span class="p">)</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">ontouchstart</tt> というリスナーがあればタッチデバイスだと認識してるっぽい.ついでにググると, <a class="reference external" href="https://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript/4819886#4819886">https://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript/4819886#4819886</a> みたいなんが出てくる.みんな苦労してるっぽい.今回はそこまで精度はいらなくて,最悪タッチデバイスじゃないとこでツールチップが表示されなくても問題ないなって感じなので, Bootstrap と StackOverflow の回答の合わせ技で,以下の判定でいくことにした:</p>
<pre class="literal-block">
export function isTouchDevice() {
return ('ontouchstart' in document.documentElement)
|| (window.DocumentTouch && document instanceof DocumentTouch)
;
}
</pre>
<p>で, <tt class="docutils literal">isTouchDevice</tt> な時はツールチップを登録しないようにした.</p>
</div>
<div class="section" id="css">
<h2>CSS を書く<a class="headerlink" href="#css" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>デフォルトでは, Tooltip.js は無地の <tt class="docutils literal"><span class="pre">z-index</span></tt> だけが調整されたツールチップを出してくる.なので,これにスタイル付けもしなきゃいけない.要素的には,</p>
<ul class="simple">
<li><tt class="docutils literal">.tooltip</tt> がツールチップ全体</li>
<li><tt class="docutils literal">.tooltip <span class="pre">.tooltip-arrow</span></tt> が矢印</li>
<li><tt class="docutils literal">.tooltip <span class="pre">.tooltip-inner</span></tt> が中身</li>
</ul>
<p>になってるっぽい.まずツールチップに余白と背景,外形を設定しておく:</p>
<pre class="literal-block">
.tooltip {
background-color: #ffffff;
border-radius: 6px;
}
.tooltip .footnote-tooltip-content {
padding: 4px 10px;
}
</pre>
<p><tt class="docutils literal"><span class="pre">footnote-tooltip-content</span></tt> は JavaScript でツールチップの中身を生成時に指定しておいたクラス.で,ここからが本体だが,まずツールチップのための三角形を作る.三角形を作る方法は割と知られている border を作る方法でやる.どういうのかというと, border の境目って斜めになってるじゃん? これブロックの幅 0 にして余白空けて,余白の長さのボーダ作ったら三角形 4 つできるよね? 3 つ透過にしたら 1 つ三角形手に入るじゃんとかいう,誰が考えたか分かんないけどその発想はなかったな奴.図で書くと分かりやすいんだが,そこまでの余力はないので頑張って頭で想像してくれ.それをやるのが次の CSS :</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span></pre></div></td><td class="code"><div><pre><span></span><span class="p">.</span><span class="nc">tooltip</span><span class="w"> </span><span class="p">.</span><span class="nc">tooltip-arrow</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">margin</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="w"> </span><span class="k">border-width</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">border-style</span><span class="p">:</span><span class="w"> </span><span class="kc">solid</span><span class="p">;</span>
<span class="w"> </span><span class="k">border-color</span><span class="p">:</span><span class="w"> </span><span class="mh">#ffffff</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">.</span><span class="nc">tooltip</span><span class="o">[</span><span class="nt">x-placement</span><span class="o">^=</span><span class="s2">"bottom"</span><span class="o">]</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">margin-top</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="kt">px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">.</span><span class="nc">tooltip</span><span class="o">[</span><span class="nt">x-placement</span><span class="o">^=</span><span class="s2">"bottom"</span><span class="o">]</span><span class="w"> </span><span class="p">.</span><span class="nc">tooltip-arrow</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">border-left-color</span><span class="p">:</span><span class="w"> </span><span class="kc">transparent</span><span class="p">;</span>
<span class="w"> </span><span class="k">border-top-color</span><span class="p">:</span><span class="w"> </span><span class="kc">transparent</span><span class="p">;</span>
<span class="w"> </span><span class="k">border-right-color</span><span class="p">:</span><span class="w"> </span><span class="kc">transparent</span><span class="p">;</span>
<span class="w"> </span><span class="k">top</span><span class="p">:</span><span class="w"> </span><span class="mi">-10</span><span class="kt">px</span><span class="p">;</span>
<span class="w"> </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="nb">calc</span><span class="p">(</span><span class="mi">50</span><span class="kt">%</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">5</span><span class="kt">px</span><span class="p">);</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal"><span class="pre">.tooltip[x-placement^="bottom"]</span></tt> で <tt class="docutils literal"><span class="pre">margin-top:</span> 5px;</tt> を指定して,まず三角形を表示する領域を確保してる.で,三角形の領域の <tt class="docutils literal">width</tt> と <tt class="docutils literal">height</tt> を 0 にして, <tt class="docutils literal">margin</tt> でボーダを描く領域を確保してる.後は, <tt class="docutils literal">border</tt> 作って <tt class="docutils literal">left</tt> と <tt class="docutils literal">top</tt> , <tt class="docutils literal">right</tt> を透過させ,中心点を上に持ってくだけ.中心は,上に確保した <tt class="docutils literal"><span class="pre">margin-top:</span> 5px;</tt> とボーダの長さ <tt class="docutils literal">5px</tt> で合計 <tt class="docutils literal">10px</tt> ずれてるため, <tt class="docutils literal"><span class="pre">-10px</span></tt> 上にすればいい.後,右に <tt class="docutils literal">5px</tt> ずれてるので,それも戻す. <tt class="docutils literal">calc(50% - 5px)</tt> してるのはツールチップの中心に置くため.</p>
<p>後いい感じに影をつける.ツールチップ本体の方は, <tt class="docutils literal"><span class="pre">box-shadow</span></tt> で適当につけてやればいいんだが,問題は三角形の方.普通に <tt class="docutils literal"><span class="pre">box-shadow</span></tt> を使うと四角形の周りに影ができるので,ツールチップ本体にかぶったり形が違ったり,色々良くない.これは,三角形の作り方を利用すればいい感じに解決できる.三角形は上部分が投下されてるので, <tt class="docutils literal">overflow: hidden</tt> を使うと上部分だけ残してはみ出す何かは消すみたいなことができる.なので,三角形の周りにはみ出してもいいので適当に影を作って, <tt class="docutils literal">overflow: hidden</tt> によってはみ出した部分を抹消するみたいな荒技ができる.これを使って以下のスタイルを書いた:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div><pre><span></span><span class="w"> </span> .tooltip {
<span class="gi">+ box-shadow: rgba(0,0,0,0.2) 0px 0px 12px 0px;</span>
<span class="w"> </span> }
<span class="w"> </span> .tooltip .tooltip-arrow {
<span class="gi">+ overflow: hidden;</span>
<span class="w"> </span> }
<span class="gi">+ .tooltip .tooltip-arrow::after {</span>
<span class="gi">+ content: "";</span>
<span class="gi">+ position: absolute;</span>
<span class="gi">+ width: 5px;</span>
<span class="gi">+ height: 5px;</span>
<span class="gi">+ transform: rotate(45deg);</span>
<span class="gi">+ left: calc(50% - 5px);</span>
<span class="gi">+ box-shadow: rgba(0,0,0,0.2) 0px -3px 12px 0px;</span>
<span class="gi">+ background-color: transparent;</span>
<span class="gi">+ }</span>
</pre></div></td></tr></table></div>
<p>三角形の影は辺の長さ <tt class="docutils literal">10px</tt> の正方形を 45 度回転させて, <tt class="docutils literal"><span class="pre">box-shadow</span></tt> で作っている <a class="footnote-reference" href="#standard-css-triangle" id="auto-id-3">[2]</a> .</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>脚注のためのツールチップを導入した.最近,ブログの調整しかしてない気がしてきたな...</p>
<table class="docutils footnote" frame="void" id="bootstrap-touch-device-detection" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><a class="reference external" href="https://github.com/twbs/bootstrap/blob/v4.3.1/js/src/tooltip.js#L320">https://github.com/twbs/bootstrap/blob/v4.3.1/js/src/tooltip.js#L320</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="standard-css-triangle" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[2]</a></td><td>というかこれが本来の三角形の作り方ではある.ただ,ツールチップ本体とかぶる部分の影のいい感じの消し方が分からんかった.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/add-tooltip-for-footnote.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/add-tooltip-for-footnote.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>ブログの overflow 時のスタイル設定を見直す2019-04-15T04:27:48+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-15:/blog/posts/2019/04/fix-overflow-settings/<p>ブログの CSS で,幅がはみ出るような要素のスタイルを幾つか修正したので,その対応記録.</p>
<div class="section" id="auto-id-1">
<h2>経緯<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>うちのブログではタイ …</p></div><p>ブログの CSS で,幅がはみ出るような要素のスタイルを幾つか修正したので,その対応記録.</p>
<div class="section" id="auto-id-1">
<h2>経緯<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>うちのブログではタイプライタ体や数式をよく使う.これは僕がプログラミングと数学寄りの記事を良く書くからだけど,ちょっと問題も起きていた.パソコンでの閲覧時はそれほど大きな問題にはならないんだが,スマフォなどの画面幅が短いモバイル端末ではタイプライタ体の文字が画面幅からはみ出て表示されて,閲覧の快適さがあまりなかった (誰から言われたとかではなく,単に僕が見る時不便だと感じていた).</p>
<p>問題となっていた要素は,以下のもの:</p>
<dl class="docutils">
<dt>インラインリテラル</dt>
<dd><tt class="docutils literal">``inline literal``</tt> で書けるやつ.プログラム片とかを書くのに使っていて, <tt class="docutils literal">tt</tt> タグを使って変換される.</dd>
<dt>数式</dt>
<dd><p class="first">以下の記法で書けるやつ:</p>
<pre class="literal-block">
.. math::
\forall x.\, x = x
</pre>
<p class="last">これは,うちのブログだと MathML に変換して, MathJax でもフォールバック描画している.</p>
</dd>
<dt>ハイライト付きコードブロック</dt>
<dd><p class="first">以下の記法で書けるやつ:</p>
<pre class="literal-block">
.. code-block::
some code
</pre>
<p class="last">うちのブログだと,デフォルトで行番号を付けている.行番号は, <tt class="docutils literal">table</tt> タグで付けるのとインラインに付加するのの 2 通りが選べ,このブログでは <tt class="docutils literal">table</tt> タグを使っている.</p>
</dd>
</dl>
<p>これらは,表示範囲内に収まらない場合でも関係なく,表示枠を超えて表示される.特に,ハイライト付きコードブロックと数式は,テーマで対応されていないため問題が起きている.</p>
</div>
<div class="section" id="css">
<h2>CSS で表示範囲を超える場合のスタイルを指定する<a class="headerlink" href="#css" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>CSS には内容が表示範囲を超える場合の挙動を設定するプロパティがある.</p>
<p>まず表示範囲を超える場合の改行制御を指定する, <tt class="docutils literal"><span class="pre">overflow-wrap</span></tt> プロパティがある. <tt class="docutils literal"><span class="pre">overflow-wrap</span></tt> では,</p>
<dl class="docutils">
<dt>normal</dt>
<dd>空白などの通常の単語分割位置で分割する.</dd>
<dt>anywhere</dt>
<dd>任意の場所で分割を行うが,一応最小固有寸法を計算する時折り返し可能位置というものが考慮されるらしい.ブラウザの対応状況がよろしくないので,ないものと思って良さそう.</dd>
<dt>break-word</dt>
<dd>anywhere と同じだが,最小固有寸法を計算する時に折り返し可能位置を考慮しない.</dd>
</dl>
<p>正直固有寸法とか良く分からんがとりあえず, <tt class="docutils literal"><span class="pre">break-word</span></tt> を指定しておけば良さそう.デフォルトでは <tt class="docutils literal">normal</tt> になる.インラインリテラルの方はこのプロパティを使った:</p>
<pre class="literal-block">
article.single tt {
overflow-wrap: break-word;
}
</pre>
<p>これで,折り返しを強制的にできる.</p>
<p>もう1つ,ブロック単位で使えるのが, overflow プロパティだ.特に今回は,左右の境界に関する条件で,これは <tt class="docutils literal"><span class="pre">overflow-x</span></tt> で指定できる. <tt class="docutils literal"><span class="pre">overflow-x</span></tt> では,</p>
<dl class="docutils">
<dt>visible</dt>
<dd>表示範囲を超える場合でも,そのまま表示する.</dd>
<dt>hidden</dt>
<dd>表示範囲を超える部分は,切り取って表示しない.</dd>
<dt>scroll</dt>
<dd>hidden と同じく内容を切り取るが,スクロールバーで内容をスクロールできるようにする.</dd>
<dt>auto</dt>
<dd>ブラウザごとの仕様に任せる.大抵は scroll と同じになる.</dd>
</dl>
<p>を指定できるらしい.デフォルトは, <tt class="docutils literal">visible</tt> になっている.今回は, <tt class="docutils literal"><span class="pre">overflow-x:</span> auto</tt> を使うことにした.数式の方はこのプロパティが特に指定されていなかったので,指定するようにした.また,ハイライト付きコードブロックには既にこのプロパティは指定されていて,とある事情でこのプロパティが機能していなかった.なのでその事情をなんとかした.</p>
<p>数式の方は以下のスタイルを追加した:</p>
<pre class="literal-block">
article.single mjx-container,
article.single math {
overflow-x: auto;
}
</pre>
<p><tt class="docutils literal">math</tt> タグは MathML のブロック, <tt class="docutils literal"><span class="pre">mjx-container</span></tt> は MathJax が MathML を解釈後に挿入するブロックだ.これで,スクロールされるようになる.</p>
<p>さて,問題のハイライト付きコードブロックだが, <tt class="docutils literal">table</tt> タグは表示幅がデフォルトで固定じゃないため,いい感じに表示幅が広がってしまうらしい.そのため,テーブルの中のコードブロックでは <tt class="docutils literal"><span class="pre">overflow-x</span></tt> プロパティが指定されているんだが,そのコードブロックの表示幅に合わせてテーブルが広がってしまうため,結果表示幅を超えてしまうっぽい.で,テーブルの表示幅を固定したい場合, <tt class="docutils literal"><span class="pre">table-layout:</span> fixed; width: 100%;</tt> を使うといいらしい.このプロパティ自体は,表の列幅をいい感じに調整しないで固定幅にするプロパティらしいのだが,結果的にテーブルの幅も固定されるらしい.このままだと,行番号はいい感じに表示してくれないので,最終的に次のスタイルを指定した:</p>
<pre class="literal-block">
article.single table.highlighttable {
width: 100%;
table-layout: fixed;
}
article.single table.highlighttable td {
border-style: none;
padding: 0px;
}
article.single table.highlighttable td.linenos {
width: 2.5em;
}
article.single table.highlighttable td.linenos pre {
border-left: 0px;
padding-right: 0.8em;
background-color: inherit;
text-align: right;
}
</pre>
<p>まあテーマの元々のテーブル設定を無効にするため色々やった.この対応は,本家に <a class="reference external" href="https://github.com/alexandrevicenzi/Flex/pull/173">PR</a> も投げておいた.マージされれば修正されるだろう.</p>
</div>
<div class="section" id="auto-id-2">
<h2>まとめ<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>画面幅が短い時にもいい感じになるよう, Flex テーマの CSS に修正を加えた.これで,スマフォの閲覧体験は改善されるはずだ.</p>
</div>
<div class="section" id="auto-id-3">
<h2>追記 (2019/04/15)<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Chrome だと, <tt class="docutils literal">a</tt> タグもうまく改行されないっぽいので, <tt class="docutils literal">a</tt> タグにも <tt class="docutils literal"><span class="pre">overflow-wrap:</span> <span class="pre">break-word;</span></tt> を追加する必要があるっぽかった.</p>
<p>あと,その関係でテーブルを使ってる footnote もダメみたいなので, footnote の方はハイライト付きコードブロックと同じ対応をした.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/fix-overflow-settings.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/fix-overflow-settings.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>MathML で数式を表示する2019-04-14T10:44:55+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-14:/blog/posts/2019/04/fix-math-settings/<p>reStructuredText は数式表示に対応している.ただデフォルトのレンダリング表示がいまいちだったので,ちょっといじった.その備 …</p><p>reStructuredText は数式表示に対応している.ただデフォルトのレンダリング表示がいまいちだったので,ちょっといじった.その備忘録.</p>
<div class="section" id="math-docutils">
<h2>math ディレクティブと docutils の設定<a class="headerlink" href="#math-docutils" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>reStructuredText には math ディレクティブというものが標準で搭載されていて <a class="footnote-reference" href="#math-directive-spec" id="auto-id-1">[1]</a> , <tt class="docutils literal">TeX</tt> の記法を使って以下のように数式が埋め込める:</p>
<pre class="literal-block">
.. math::
\forall a, b \in \mathbb{N}.\, a \leq b \implies \sqrt{a} \leq \sqrt{b}
</pre>
<p>これは特に何もしなくても <tt class="docutils literal">docutils</tt> でコンパイルして HTML にしてくれる.なので, reStructuredText を使っている場合は簡単な数式なら Pelican のブログ記事で普通に使える.これ自体は素晴らしいんだが,出される HTML は数学記号を Unicode 表現にして変数をイタリックにしただけで,空白制御とかはあまり考慮されておらず,フォントもあまり良くない.なので,もうちょっと何とか出来ないかということで,色々調べた.</p>
<p><tt class="docutils literal">docutils</tt> の出力オプションとして <a class="reference external" href="http://docutils.sourceforge.net/docs/user/config.html#math-output">math_output</a> というオプションがあり色々弄れるらしい.ここに指定できる出力の仕方は,以下の 4 通り:</p>
<dl class="docutils">
<dt>HTML</dt>
<dd>デフォルトの出力方法. <tt class="docutils literal">i</tt> タグや <tt class="docutils literal">sup</tt> タグなどを駆使して簡単な数式レンダリングを行う.カスタムCSSファイルを引数として指定すると, CSS が必要な時だけ埋め込んでくれる.</dd>
<dt>MathJax</dt>
<dd>MathJax を使ってレンダリングを行う.引数に MathJax のライブラリファイルの指定が必須.</dd>
<dt>MathML</dt>
<dd>MathML を使ってレンダリングを行う.引数にコマンドを指定すると,そのコマンドでコンパイルしてくれる.</dd>
<dt>LaTeX</dt>
<dd>数式表現をそのまま埋め込む.</dd>
</dl>
<p>で,今回は気になったので MathML を使ってみた.引数にコマンドを指定しない場合標準のコンパイラで MathML に変換してくれる.なお,標準のは <tt class="docutils literal">\ldotp</tt> が使えなかったりちょっと不便なところがあるが, <tt class="docutils literal">latexml</tt> などを使うと使える記号をもうちょっと増やせるみたい.今回は,妥協してフルに <tt class="docutils literal">LaTeX</tt> 使いたかったら PDF で埋め込めばええやろという気持ちで,標準のをそのまま使うことにした.</p>
<p><tt class="docutils literal">pelicanconf.py</tt> に次の設定を足すだけで, MathML が使えるようになる:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="w"> </span> DOCUTILS_SETTINGS = {
<span class="w"> </span> ...
<span class="gi">+ 'math_output': 'MathML',</span>
<span class="w"> </span> }
</pre></div></td></tr></table></div>
</div>
<div class="section" id="auto-id-2">
<h2>MathML のフォールバック<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ところで, MathML を使う場合気になるのが,ブラウザの対応状況だ.というわけで, <a class="reference external" href="https://caniuse.com/#feat=mathml">サポート状況</a> を覗きに行ってみると,見事に壊滅状態にあってサポートしてるの Firefox / Safari ぐらいやんってなった. Edge は現状サポート予定はなくて, Chrome は提案は出てるもののやっぱりサポート予定はないっぽい.</p>
<p>なので, MathML のフォールバックを行うことを考えたい. MathJax が MathML での入力に対応してるので導入してみたのだが,これが webpack とかなり相性が悪い構成になっているっぽい.本家にも <a class="reference external" href="https://github.com/mathjax/MathJax/issues/1629">イシュー</a> が立っているわけだが,現状の構成でとても対応できるとは思えない.で,色々探っていたら,次期 MathJax v3 では TypeScript を使って書いていていい感じにモジュール構成を取り入れているため, webpack にももちろん対応できるという話が上がっていた.で,まだ正式リリースじゃなくてベータ版なんだけど,使ってみるかってなった.どうせレンダリング失敗しても, MathML 見れる環境なら問題ないはずだし.</p>
<p>まず, npm で <tt class="docutils literal">mathjax3</tt> をインストールする:</p>
<pre class="literal-block">
npm install -S mathjax3
</pre>
<p>で, <tt class="docutils literal">webpack.config.js</tt> に以下の設定を足す:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span></pre></div></td><td class="code"><div><pre><span></span><span class="w"> </span> resolve: {
<span class="w"> </span> alias: {
<span class="w"> </span> ...
<span class="gi">+ mathjax3$: 'mathjax3/mathjax3/mathjax.js',</span>
<span class="gi">+ mathjax3: 'mathjax3/mathjax3',</span>
<span class="w"> </span> }
<span class="w"> </span> }
<span class="w"> </span> ...
<span class="w"> </span> plugins: [
<span class="w"> </span> ...
<span class="gi">+ // to disable asyncLoad()</span>
<span class="gi">+ new webpack.NormalModuleReplacementPlugin(</span>
<span class="gi">+ /AsyncLoad\.js/,</span>
<span class="gi">+ (resource) => {</span>
<span class="gi">+ if (resource.context.endsWith('mathjax3/util')) {</span>
<span class="gi">+ resource.request = resource.request.replace(/AsyncLoad/,"AsyncLoad-disabled");</span>
<span class="gi">+ }</span>
<span class="gi">+ }</span>
<span class="gi">+ )</span>
<span class="w"> </span> ],
</pre></div></td></tr></table></div>
<p>最初の設定はいいとして,2番目の設定についてだけど, webpack はコード解析して依存関係を解決してるんだけどその解析が MathJax v3 の <tt class="docutils literal">AsyncLoad</tt> モジュールで死ぬという問題があるらしい.で, webpack 使ってバンドルする場合そもそも非同期 import いらないねって話があって, MathJax v3 では webpack 向けに <tt class="docutils literal"><span class="pre">AsyncLoad-disabled.js</span></tt> というモジュールを提供することにしたらしい <a class="footnote-reference" href="#mathjax3-issue-88" id="auto-id-5">[2]</a> .で, webpack を使う場合は <tt class="docutils literal">AsyncLoad</tt> モジュールを <tt class="docutils literal"><span class="pre">AsyncLoad-disabled</span></tt> モジュールに置換することでその問題を解決できる.それをやるのが上のコード.</p>
<p>後は, JavaScript で,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">MathJax</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">'mathjax3'</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">MathML</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">'mathjax3/input/mathml'</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">CHTML</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">'mathjax3/output/chtml'</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">browserAdaptor</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">'mathjax3/adaptors/browserAdaptor'</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">RegisterHTMLHandler</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s1">'mathjax3/handlers/html'</span><span class="p">;</span>
<span class="nx">RegisterHTMLHandler</span><span class="p">(</span><span class="nx">browserAdaptor</span><span class="p">());</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">MathJaxDocument</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">MathJax</span><span class="p">.</span><span class="nb">document</span><span class="p">(</span><span class="nb">document</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">InputJax</span><span class="o">:</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">MathML</span><span class="p">(),</span>
<span class="w"> </span><span class="nx">OutputJax</span><span class="o">:</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">CHTML</span><span class="p">({</span>
<span class="w"> </span><span class="nx">fontURL</span><span class="o">:</span><span class="w"> </span><span class="s1">'https://cdn.rawgit.com/mathjax/mathjax-v3/3.0.0-beta.3/mathjax2/css'</span><span class="p">,</span>
<span class="w"> </span><span class="p">}),</span>
<span class="p">});</span>
<span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">loadMathJaxDocument</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">MathJaxDocument</span>
<span class="w"> </span><span class="p">.</span><span class="nx">findMath</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="nx">compile</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="nx">getMetrics</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="nx">typeset</span><span class="p">()</span>
<span class="w"> </span><span class="p">.</span><span class="nx">updateDocument</span><span class="p">()</span>
<span class="w"> </span><span class="p">;</span>
<span class="p">}</span>
</pre></div></td></tr></table></div>
<p>みたいなんを書いて, DOM のロード後のタイミングで <tt class="docutils literal">loadMathJaxDocument</tt> 関数を呼び出せば良い. MathJax v3 は結構モジュールの導入のおかげで治安が良くなってて良い.以下が最終的なレンダリング結果になる:</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∀</mi><mi>a</mi><mo separator="true">,</mo><mi>b</mi><mo>∈</mo><mi mathvariant="double-struck">N</mi><mi mathvariant="normal">.</mi><mtext> </mtext><mi>a</mi><mo>≤</mo><mi>b</mi><mtext> </mtext><mo>⟹</mo><mtext> </mtext><msqrt><mi>a</mi></msqrt><mo>≤</mo><msqrt><mi>b</mi></msqrt></mrow><annotation encoding="application/x-tex">
\forall a, b \in \mathbb{N}.\, a \leq b \implies \sqrt{a} \leq \sqrt{b}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8249em;vertical-align:-0.136em;"></span><span class="mord mathbb">N</span><span class="mord">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7184em;vertical-align:-0.024em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.04em;vertical-align:-0.1908em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8492em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord" style="padding-left:0.833em;"><span class="mord mathnormal">a</span></span></span><span style="top:-2.8092em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em;"><svg height="1.08em" preserveaspectratio="xMinYMin slice" viewbox="0 0 400000 1080" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M95,702
c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54
c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10
s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429
c69,-144,104.5,-217.7,106.5,-221
l0 -0
c5.3,-9.3,12,-14,20,-14
H400000v40H845.2724
s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7
c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z
M834 80h400000v40h-400000z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.1908em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.04em;vertical-align:-0.0589em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9811em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord" style="padding-left:0.833em;"><span class="mord mathnormal">b</span></span></span><span style="top:-2.9411em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em;"><svg height="1.08em" preserveaspectratio="xMinYMin slice" viewbox="0 0 400000 1080" width="400em" xmlns="http://www.w3.org/2000/svg"><path d="M95,702
c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54
c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10
s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429
c69,-144,104.5,-217.7,106.5,-221
l0 -0
c5.3,-9.3,12,-14,20,-14
H400000v40H845.2724
s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7
c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z
M834 80h400000v40h-400000z"></path></svg></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.0589em;"><span></span></span></span></span></span></span></span></span></span></div>
<p>レンダリングがちゃんと出来ていなかったら,ぜひ使ってるブラウザを教えて欲しい.修正するかは分からないけど.</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ブログの数式表示を改善した. MathJax v3 がまだベータ版なので,ちょっとまめに更新は確認していきたい.</p>
<p>後ちょっとレンダリングが遅めなのが気になるがまあしゃーないね. MathML 標準対応してほちい.</p>
<table class="docutils footnote" frame="void" id="math-directive-spec" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-1">[1]</a></td><td><a class="reference external" href="http://docutils.sourceforge.net/docs/ref/rst/directives.html#math">http://docutils.sourceforge.net/docs/ref/rst/directives.html#math</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="mathjax3-issue-88" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[2]</a></td><td><a class="reference external" href="https://github.com/mathjax/mathjax-v3/issues/88">https://github.com/mathjax/mathjax-v3/issues/88</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/fix-math-settings.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/fix-math-settings.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Functor / Applicative / Monad が表すもの2019-04-13T11:42:41+09:002022-12-04T14:38:40+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-13:/blog/posts/2019/04/generalizing-transformation/<p><a class="reference external" href="https://kazu-yamamoto.hatenablog.jp/entry/2019/04/11/111238">https://kazu-yamamoto.hatenablog.jp/entry/2019/04/11/111238</a> の記事に触発されて,ちょっと書く気になった.こちらも面白い記事なので,ぜひ参照してほしい …</p><p><a class="reference external" href="https://kazu-yamamoto.hatenablog.jp/entry/2019/04/11/111238">https://kazu-yamamoto.hatenablog.jp/entry/2019/04/11/111238</a> の記事に触発されて,ちょっと書く気になった.こちらも面白い記事なので,ぜひ参照してほしい.</p>
<p>Haskell 2020 で Applicative が追加される見込みだ (そもそもちゃんと 2020 年に出るのか怪しそうだが).それを踏まえて,標準ライブラリに入る Haskell の特徴的な一連の型クラス Functor / Applicative / Monad の個人的な捉え方を書いておこうと思う.なお,あくまで個人的な捉え方なので,形式的でないし,広く受け入れられている考え方とは乖離している可能性があるので,そこは注意してほしい.</p>
<div class="section" id="auto-id-1">
<h2>概要<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>それぞれの型クラスが表すものは端的に言えば,</p>
<dl class="docutils">
<dt>Functor</dt>
<dd>変換の一般化</dd>
<dt>Applicative</dt>
<dd>関数適用の一般化</dd>
<dt>Monad</dt>
<dd>手続きの結合の一般化</dd>
</dl>
<p>だと思う.</p>
<ul class="simple">
<li>手続きの結合の特殊な場合が,関数適用 (<tt class="docutils literal">Monad m => Applicative m</tt>)</li>
<li>一般的な関数適用の特殊な場合が,変換の一般化 (<tt class="docutils literal">Applicative m => Functor m</tt>)</li>
</ul>
<p>という関係になっている.なお, Haskell 2010 では <tt class="docutils literal">Monad m => Functor m</tt> は強制されていなかったが, Haskell 2020 では <tt class="docutils literal">Monad m => Applicative m</tt> / <tt class="docutils literal">Applicative m => Functor m</tt> の階層がクラスに指定されるようになる <a class="footnote-reference" href="#amp-proposal-for-haskell2020" id="auto-id-2">[2]</a> .</p>
<p>では,それぞれの型クラスを見ていく.</p>
</div>
<div class="section" id="functor">
<h2>Functor 型クラス<a class="headerlink" href="#functor" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Functor クラスは,以下のようになる <a class="footnote-reference" href="#minimal-class-definition" id="auto-id-3">[3]</a> :</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">-- | The 'Functor' class can generalize a transformation.</span>
<span class="c1">--</span>
<span class="c1">-- Instances of 'Functor' should satisfy the following laws:</span>
<span class="c1">--</span>
<span class="c1">-- [/identity/]</span>
<span class="c1">--</span>
<span class="c1">-- @'fmap' 'id' = 'id'@</span>
<span class="c1">--</span>
<span class="c1">-- [/composition/]</span>
<span class="c1">--</span>
<span class="c1">-- @'fmap' (f . g) = 'fmap' f . 'fmap' g@</span>
<span class="c1">--</span>
<span class="c1">-- A given type has at most one valid instance of 'Functor'.</span>
<span class="c1">-- And, if the identity law is satisfied, the composition law is also satisfied.</span>
<span class="c1">--</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">Functor</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
</pre></div></td></tr></table></div>
<p>任意の変換 <tt class="docutils literal">f :: a <span class="pre">-></span> b</tt> を <tt class="docutils literal">fmap f :: m a <span class="pre">-></span> m b</tt> という変換に一般化できるのが, Functor だ.ただ,型が合ってれば何でもいいかというと,それだけではあまりにも治安が悪い.なので,コメントに書いてある通り</p>
<dl class="docutils">
<dt>恒等関数の保存 (preserve identity)</dt>
<dd><p class="first">何もしない変換 (<tt class="docutils literal">id :: a <span class="pre">-></span> a = \x <span class="pre">-></span> x</tt>) を一般化すると,やっぱり何もしない変換になる:</p>
<pre class="last literal-block">
fmap id = id
</pre>
</dd>
<dt>合成の保存 (preserve composition)</dt>
<dd><p class="first">一般化する前に合成しても,後で合成しても,結果が同じになる:</p>
<pre class="last literal-block">
fmap (f . g) = fmap f . fmap g
</pre>
</dd>
</dl>
<p>を満たす必要がある.俗に言われる <tt class="docutils literal">Functor</tt> 則である.ただ実は,恒等関数の保存を満たせば合成の保存も自動的に満たせることが分かっている <a class="footnote-reference" href="#slim-functor-law-by-free" id="auto-id-4">[1]</a> .恒等関数の保存はモチベーションとしてはかなり理解しやすい.何もしない変換を一般化すると,意味のある変換になるというのは少し許容しがたい.そして,ただそれだけを条件に課すだけで, <tt class="docutils literal">fmap</tt> の実装が唯一に決まるというのは不思議で面白い.これは,見過ごされがちだが, <tt class="docutils literal">fmap</tt> が多相であることがかなり効いている.ほぼ全ての高次なデータ型は, Functor になり,その実装も唯一に決まる.</p>
<p>ところで, Functor に課す条件は本当にこれだけで妥当なのだろうか? 確かに多くのデータ型で一貫した実装を提供できるということは何かしら意味を持ちそうだが,それにしても条件が,多相的で「何もしない変換を一般化すると,何もしない変換になる」というだけではそれほど強い制約にはなりそうにない.この実装が具体的に意味を持つのかは別のトピックで,横道に逸れそうなので後述の <a class="reference internal" href="#auto-id-7">Functor の妥当性</a> で述べることにする.少なくとも,実装が唯一に決まる変換の一般化の1つの形が, <tt class="docutils literal">Functor</tt> であるという見方はできるだろう.ここでは,そこまで抽象的な制約に意味があるかについては,確かに議論の余地があるとだけ言っておく.</p>
</div>
<div class="section" id="applicative">
<h2>Applicative 型クラス<a class="headerlink" href="#applicative" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Applicative クラスは,以下のようになる <a class="footnote-reference" href="#minimal-class-definition" id="auto-id-5">[3]</a> :</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span>
<span class="normal">28</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">-- | The 'Applicative' class provides general function application.</span>
<span class="c1">--</span>
<span class="c1">-- Instances of 'Applicative' should satisfy the following laws:</span>
<span class="c1">--</span>
<span class="c1">-- [/identity/]</span>
<span class="c1">--</span>
<span class="c1">-- @'pure' 'id' '<*>' x = x@</span>
<span class="c1">--</span>
<span class="c1">-- [/composition/]</span>
<span class="c1">--</span>
<span class="c1">-- @'pure' (.) '<*>' u '<*>' v '<*>' w = u '<*>' (v '<*>' w)@</span>
<span class="c1">--</span>
<span class="c1">-- [/homomorphism/]</span>
<span class="c1">--</span>
<span class="c1">-- @'pure' f '<*>' 'pure' x = 'pure' (f x)@</span>
<span class="c1">--</span>
<span class="c1">-- [/interchange/]</span>
<span class="c1">--</span>
<span class="c1">-- @u '<*>' 'pure' y = 'pure' ('$' y) '<*>' u@</span>
<span class="c1">--</span>
<span class="c1">-- As a consequence of these laws, the 'Functor' instance for @m@ will satisfy</span>
<span class="c1">--</span>
<span class="c1">-- > pure f <*> x = fmap f x</span>
<span class="c1">--</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">Functor</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Applicative</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="p">(</span><span class="o"><*></span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
</pre></div></td></tr></table></div>
<p>Applicative クラスは,実は提唱論文では idiom と呼ばれる Applicative を用いた言語と,その為のブラケット記法というものがセットになっていた.これは今日では Applicative style と言う名前で親しまれている. Applicative style は以下の形でプログラムを書いていく手法だ:</p>
<pre class="literal-block">
pure f <*> x1 <*> x2 <*> ...
</pre>
<p>この手法において必要なのは, Applicative クラスのメソッドだけだ.また GHC では取り込まれなかった為,忘れ去られてしまったが,論文中では次の記法も提唱されていた:</p>
<pre class="literal-block">
[| f x1 x2 ... |]
</pre>
<p>これは上の <tt class="docutils literal">pure</tt> と <tt class="docutils literal"><*></tt> で書かれた式の糖衣構文になっている.かなり関数適用の一般化として直感的な記法だ. Applicative はこの idiom に特化した Functor と Monad の中間と位置づけられたクラスだ.</p>
<p>もちろん Applicative もただ型があっているだけでは治安が悪いので,法則が用意されている.ただ使い方と裏腹に,その法則はかなりややこしい. Applicative が満たすべき法則, <tt class="docutils literal">Applicative</tt> 則は以下のものになる.</p>
<dl class="docutils">
<dt>恒等関数の保存 (preserve identity)</dt>
<dd><p class="first">何もしない変換 (<tt class="docutils literal">id :: a <span class="pre">-></span> a = \x <span class="pre">-></span> x</tt>) を <tt class="docutils literal">pure id :: m (a <span class="pre">-></span> a)</tt> に埋め込んで一般化された関数適用するのは,何もしないのと同じ:</p>
<pre class="literal-block">
pure id <*> x = x
</pre>
<p>これは,ブラケット表記を使うと以下のように書ける:</p>
<pre class="literal-block">
[| id x |] = x
</pre>
<p class="last">こうすると,関数適用の一般化という感じはある.</p>
</dd>
<dt>合成の保存 (preserve composition)</dt>
<dd><p class="first">一般化された関数に合成関数を適用した結果は,一般化された関数での合成に一致する:</p>
<pre class="literal-block">
pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
</pre>
<p>これは,ブラケット表記を使うと以下のように書ける:</p>
<pre class="literal-block">
[| (\f g x -> f (g x)) u v w |] = u <*> (v <*> w)
</pre>
<p class="last">これも右側の <tt class="docutils literal"><*></tt> を無視するといい感じに関数適用の一般化をしてそうな感じは出てる.</p>
</dd>
<dt>準同型 (homomorphism)</dt>
<dd><p class="first">埋め込んだ後で一般化された関数適用をした結果と,関数適用してから埋め込んだ結果が一致する:</p>
<pre class="last literal-block">
pure f <*> pure x = pure (f x)
</pre>
</dd>
<dt>交替律 (interchange property)</dt>
<dd><p class="first"><tt class="docutils literal">pure</tt> が右にある場合に,それを左に移すことができる:</p>
<pre class="literal-block">
u <*> pure x = pure ($ x) <*> u
</pre>
<p>右固定というのが交替っぽい.もう少し交替っぽく書くと以下の感じ:</p>
<pre class="literal-block">
u <*> pure x = fmap (\f -> f x) u
</pre>
<p class="last">ここでは <tt class="docutils literal">pure f <*> x = fmap f x</tt> を使っている.左が一般化された関数適用を使っていて,右が関数適用を <tt class="docutils literal">fmap</tt> で一般化している.要は関数適用と一般化が交替していて,左は一般化してから関数適用なのが,右は関数適用してから一般化みたいな感じ.</p>
</dd>
<dt>親の <tt class="docutils literal">Functor</tt> インスタンスとの整合性</dt>
<dd><p class="first"><tt class="docutils literal">pure</tt> / <tt class="docutils literal"><*></tt> から決定される <tt class="docutils literal">Functor</tt> の実装が,元の <tt class="docutils literal">fmap</tt> と整合性が取れている:</p>
<pre class="literal-block">
pure f <*> x = fmap f x
</pre>
<p>ところで実は,これは前の4つが満たされていれば,自動的に満たされる.まず,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">pure</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="c1">-- Applicative の恒等関数の保存</span>
<span class="p">(</span><span class="n">pure</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o"><*></span><span class="p">)</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="p">(</span><span class="n">pure</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o"><*></span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="p">(</span><span class="n">pure</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="p">(</span><span class="o">.</span><span class="p">)</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="c1">-- Applicative の合成の保存</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">g</span><span class="p">)</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="c1">-- 準同型</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="p">(</span><span class="n">pure</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">g</span><span class="p">)</span><span class="w"> </span><span class="o"><*></span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">x</span>
</pre></div></td></tr></table></div>
<p class="last">から <tt class="docutils literal">\f <span class="pre">-></span> (pure f <span class="pre"><*>)</span></tt> は <tt class="docutils literal">Functor</tt> 則を満たす.さらに, <tt class="docutils literal">Functor</tt> のインスタンスは一意なので,この実装は <tt class="docutils literal">fmap</tt> と一致する.よって, <tt class="docutils literal">pure f <*> x = fmap f x</tt> が成り立つことになる.</p>
</dd>
</dl>
<p>一体このような法則はどこからきたのだろうか? 提唱論文では,実は <tt class="docutils literal">Applicative</tt> と同じ能力を持つ別のクラスも紹介されている.それは以下のクラスだ:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span>
<span class="normal">27</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">-- | The 'Monoidal' class is generalized 'Monoid'.</span>
<span class="c1">--</span>
<span class="c1">-- Instances of 'Monoidal' should satisfy the following laws:</span>
<span class="c1">--</span>
<span class="c1">-- [/naturality/]</span>
<span class="c1">--</span>
<span class="c1">-- @'fmap' (\(x, y) -> (f x, g y)) (u '>*<' v) = 'fmap' f u '>*<' 'fmap' g v@</span>
<span class="c1">--</span>
<span class="c1">-- [/left identity/]</span>
<span class="c1">--</span>
<span class="c1">-- @'fmap' 'snd' ('unit' >*< v) = v@</span>
<span class="c1">--</span>
<span class="c1">-- [/right identity/]</span>
<span class="c1">--</span>
<span class="c1">-- @'fmap' 'fst' (u '>*<' 'unit') = u@</span>
<span class="c1">--</span>
<span class="c1">-- [/associativity/]</span>
<span class="c1">--</span>
<span class="c1">-- @</span>
<span class="c1">-- 'fmap' (\((x, y), z) -> (x, y, z)) ((u '>*<' v) '>*<' w)</span>
<span class="c1">-- = 'fmap' (\(x, (y, z)) -> (x, y, z)) (u '>*<' (v '>*<' w))</span>
<span class="c1">-- @</span>
<span class="c1">--</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">Functor</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Monoidal</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="nb">()</span>
<span class="w"> </span><span class="p">(</span><span class="o">>*<</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">Applicative</tt> は <tt class="docutils literal"><*></tt> が左は一般化された関数,右は一般化された引数のように,主と従が決まっていた. <tt class="docutils literal">Monoidal</tt> の場合,引数は同じレベルになっていて対称性がある. <tt class="docutils literal">Monoidal</tt> から <tt class="docutils literal">Applicative</tt> ,その逆はそれぞれ次のように書ける:</p>
<pre class="literal-block">
pure x = fmap (const x) unit
f <*> x = fmap (\(f, x) -> f x) $ f >*< x
unit = pure ()
x >*< y = (,) <$> x <*> y
</pre>
<p>なお,各法則が成り立つかはめんどくさいのでやらない.各自で試してみてくれ. <tt class="docutils literal">Monoidal</tt> から <tt class="docutils literal">Applicative</tt> の交替律を導くとこだけやっとくと,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">u</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="n">x</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="p">(</span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="n">const</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="c1">-- Monoidal のメソッド使って書き直し</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="n">const</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="c1">-- Functor の恒等関数の保存</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="p">(</span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="n">id</span><span class="w"> </span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="n">const</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="nb">()</span><span class="p">))</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="c1">-- naturality</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="p">(</span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="nb">()</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="c1">-- 単純化</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">((</span><span class="nf">\</span><span class="n">f</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">fst</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">unit</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">f</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="n">fst</span><span class="w"> </span><span class="p">(</span><span class="n">u</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">unit</span><span class="p">)</span><span class="w"> </span><span class="c1">-- Functor の合成の保存</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">f</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="c1">-- right identity</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="n">f</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="n">snd</span><span class="w"> </span><span class="p">(</span><span class="n">unit</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">u</span><span class="p">)</span><span class="w"> </span><span class="c1">-- left identity</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">((</span><span class="nf">\</span><span class="n">f</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">.</span><span class="w"> </span><span class="n">snd</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="c1">-- Functor の合成の保存</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="p">(</span><span class="nb">()</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="p">(</span><span class="nb">()</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="n">const</span><span class="w"> </span><span class="p">(</span><span class="o">$</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="nb">()</span><span class="p">,</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">u</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="o">...</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="n">const</span><span class="w"> </span><span class="p">(</span><span class="o">$</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="c1">-- naturality</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="nf">\</span><span class="p">(</span><span class="n">g</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="o">$</span><span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="p">(</span><span class="n">const</span><span class="w"> </span><span class="p">(</span><span class="o">$</span><span class="w"> </span><span class="n">x</span><span class="p">))</span><span class="w"> </span><span class="n">unit</span><span class="w"> </span><span class="o">>*<</span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="c1">-- Functor の恒等関数の保存</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">pure</span><span class="w"> </span><span class="p">(</span><span class="o">$</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o"><*></span><span class="w"> </span><span class="n">u</span><span class="w"> </span><span class="c1">-- Applicative のメソッドに書き直し</span>
</pre></div></td></tr></table></div>
<p>みたいな感じになる.証明が結構対称的になっていて,中間で <tt class="docutils literal">fmap ($ x) u</tt> が出てくる.関数適用の一般化が,こういう綺麗な構造から出てくると言うのは結構不思議だ.まあでも, <tt class="docutils literal">f <*> x = fmap <span class="pre">(\(f,</span> x) <span class="pre">-></span> f x) $ f >*< x</tt> という定義から考えてみると,関数適用は 1 つの変換なので <tt class="docutils literal">fmap</tt> によって一般化できるので,後は 2 つの一般化された値 <tt class="docutils literal">f :: m (a <span class="pre">-></span> b)</tt> / <tt class="docutils literal">x :: m a</tt> を1つの一般化された値にまとめることができれば勝ちで,実はこのまとめる操作こそ本質だったという話だろう.そして結合する話になってくると大事になってくるのが, Monoid でその法則を入れた結果,非対称な <tt class="docutils literal">Applicative</tt> のメソッドに法則を翻訳するとぱっと見よく分からない規則が出てくると言うわけだ.</p>
<p>まあ実装する際に, <tt class="docutils literal">Applicative</tt> であるが <tt class="docutils literal">Monad</tt> でないみたいなのを実装することはあんまないはずなので,通常は法則など気にせずともいいはずだ. <tt class="docutils literal">Applicative</tt> は使う分にはかなり直感的で, Applicative style によってまるで通常の関数適用のごとくプログラムが書ける.</p>
</div>
<div class="section" id="monad">
<h2>Monad 型クラス<a class="headerlink" href="#monad" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Monad クラスは,以下のようになる <a class="footnote-reference" href="#minimal-class-definition" id="auto-id-6">[3]</a> :</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">-- | The 'Monad' class can combine two actions.</span>
<span class="c1">--</span>
<span class="c1">-- Instances of 'Monad' should satisfy the following laws:</span>
<span class="c1">--</span>
<span class="c1">-- [/left identity/]</span>
<span class="c1">--</span>
<span class="c1">-- @'pure' x '>>=' k = k x@</span>
<span class="c1">--</span>
<span class="c1">-- [/right identity/]</span>
<span class="c1">--</span>
<span class="c1">-- @m '>>=' 'pure' = m@</span>
<span class="c1">--</span>
<span class="c1">-- [/associativity/]</span>
<span class="c1">--</span>
<span class="c1">-- @(m '>>=' f) '>>=' g = m '>>=' (\x -> f x '>>=' g)@</span>
<span class="c1">--</span>
<span class="c1">-- Furthermore, the 'Monad' and 'Applicative' operations should relate as follows:</span>
<span class="c1">--</span>
<span class="c1">-- > mf <*> mx = mf >>= \f -> mx >>= f</span>
<span class="c1">--</span>
<span class="c1">-- As a consequence of these laws, the 'Functor' instance for @m@ will satisfy</span>
<span class="c1">--</span>
<span class="c1">-- > fmap f x = x >>= pure . f</span>
<span class="c1">--</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">Applicative</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="p">(</span><span class="o">>>=</span><span class="p">)</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">b</span>
</pre></div></td></tr></table></div>
<p><tt class="docutils literal">Monad</tt> については色んな人が記事を書いてるし,それを参照しろってことで (そろそろ飽きてきた).</p>
<p>一応いくつか言っておくと,まず Haskell2020 の RFC で進んでる <tt class="docutils literal">Applicative</tt> のプロポーサルでは, no return プロポーサルも取り込まれていて, <tt class="docutils literal">return = pure</tt> のデフォルト実装が取り込まれる予定.後, <tt class="docutils literal">join</tt> も <tt class="docutils literal">Monad</tt> のメソッドとして入ることになっている.なので, <tt class="docutils literal">Monad</tt> クラスはこうも書ける:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1">-- | The 'Monad' class can combine two actions.</span>
<span class="c1">--</span>
<span class="c1">-- Instances of 'Monad' should satisfy the following laws:</span>
<span class="c1">--</span>
<span class="c1">-- [/associativity/]</span>
<span class="c1">--</span>
<span class="c1">-- @'join' . 'fmap' 'join' = 'join' . 'join'@</span>
<span class="c1">--</span>
<span class="c1">-- [/identity/]</span>
<span class="c1">--</span>
<span class="c1">-- @'join' . 'fmap' 'pure' = 'join' . 'pure' = 'id'@</span>
<span class="c1">--</span>
<span class="c1">-- Furthermore, the 'Monad' and 'Applicative' operations should relate as follows:</span>
<span class="c1">--</span>
<span class="c1">-- > mf <*> mx = join . fmap (\f -> fmap f mx) $ mf</span>
<span class="c1">--</span>
<span class="kr">class</span><span class="w"> </span><span class="kt">Applicative</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Monad</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">join</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">-></span><span class="w"> </span><span class="n">m</span><span class="w"> </span><span class="n">a</span>
</pre></div></td></tr></table></div>
<p>お馴染みの coherence condition だ. <tt class="docutils literal">join . fmap join = join . join :: m (m (m a)) <span class="pre">-></span> m a</tt> は中身を先にまとめるか外側を先にまとめるかでの coherence を表し,結合律 (associativity) と対応する. <tt class="docutils literal">join . fmap pure = join . pure = id :: m a <span class="pre">-></span> m a</tt> は中身を埋め込んでまとめるか,外側を埋め込んでまとめるかの coherence を表す.で,この合成は最終的に何もしない変換と一致し,単位元律 (identity) と対応することになる.</p>
<p>後 <tt class="docutils literal">Monad</tt> が手続きの結合を表すについてだが,実は単に 2 つの独立した手続きがあった時,それを結合するのは <tt class="docutils literal">Applicative</tt> で十分だ.手続きを繋げる時は <tt class="docutils literal">const id</tt> を一般化して適用すればいい.例えば,</p>
<pre class="literal-block">
pure (const id) <*> putStrLn "Hello" <*> putStrLn "World"
</pre>
<p>こうすると <tt class="docutils literal">putStrLn "Hello"</tt> は計算されるものの結果は無視されることになる.これは, C 言語のコンマ (,) 演算子と発想は同じだ.なお, <tt class="docutils literal">Applicative</tt> のモジュールではこれに相当する演算子 <tt class="docutils literal">*></tt> が用意されていて,次のように書ける:</p>
<pre class="literal-block">
putStrLn "Hello" *> putStrLn "World"
</pre>
<p>Applicative が Monoidal の非対称版であることを思い出すとこの結果は納得できる. 2 つの一般化された値を 1 つの一般化された値にまとめる力は, Applicative で十分手に入るのだ.では,なぜ <tt class="docutils literal">Monad</tt> が必要かと言うと,手続きを結合するのには 1 つの一般化された値にまとめるだけでは不十分で,前の手続きの結果を次の手続きで流用する力が必要になってくるときがあるからだ.具体的には条件分岐で,前の結果をもとに条件判断して,その判断に応じてそれぞれ別の計算を行いたい場合などだ.なので, <tt class="docutils literal">Monad</tt> は 2 つの一般化された値を 1 つの一般化された値にまとめるのではなく,手続きを一般化された継続と見てそれをまとめる力を持つ.この点で見た時は,以下の演算子での法則の方が覚えやすい:</p>
<pre class="literal-block">
f >=> g = \x -> f x >>= g
-- identity
f >=> pure = pure >=> f = f
-- associativity
(f >=> g) >=> h = f >=> (g >=> h)
</pre>
<p><tt class="docutils literal"><*></tt> と <tt class="docutils literal">>*<</tt> の関係と同じく, <tt class="docutils literal">>>=</tt> と <tt class="docutils literal">>=></tt> の関係は非対称 / 対称ということになる.最終的に Applicative も Monad も単位元律と結合律に落ち着いて,単に対象が違うだけと言う感じだ.</p>
</div>
<div class="section" id="auto-id-7">
<h2>Functor の妥当性<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>さて,最後に <tt class="docutils literal">Functor</tt> クラスは妥当なのかについて触れておこうと思う.と言ってもなんかソースがあるわけでなく (てかこの記事全般そうだし,ちゃんとした記事ならブログには書かないんだよなあ) 勝手に自分で考えたことだ.</p>
<p>まず,現状の <tt class="docutils literal">Functor</tt> クラスで良く見過ごされがちだがかなり大きな役割を担っているのがパラメトリック多相な <tt class="docutils literal">fmap</tt> の定義だ.この多相性のおかげで, <tt class="docutils literal">fmap</tt> が唯一の実装を持つことが保証される.どう言う風に証明を書くかは, <a class="reference external" href="https://www.schoolofhaskell.com/user/edwardk/snippets/fmap">https://www.schoolofhaskell.com/user/edwardk/snippets/fmap</a> とかをのぞいてみるのがいいと思う.</p>
<p>実装が固定できるのはいいことなのだが,逆に制約が弱すぎて大抵の高次なデータ型は <tt class="docutils literal">Functor</tt> を実装できてしまう.むしろ,高次のデータ型に対して一貫して提供されるユーティリティの1つと考える方が自然だと思う.事実, GHC では <tt class="docutils literal">DeriveFunctor</tt> という拡張が提供されている.この拡張により, <tt class="docutils literal">deriving</tt> で <tt class="docutils literal">Functor</tt> のインスタンスを導出できる.例えば,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span>
<span class="normal">9</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">data</span><span class="w"> </span><span class="kt">RecData</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">RecBound1</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">RecBound2</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">RecNode</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="p">(</span><span class="kt">RecData</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">RecData</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Functor</span><span class="w"> </span><span class="kt">RecData</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="kt">RecBound1</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">RecBound1</span>
<span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="kt">RecBound2</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">RecBound2</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="kt">RecNode</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="n">r1</span><span class="w"> </span><span class="n">r2</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">RecNode</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="p">(</span><span class="n">fmap</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">r1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">fmap</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="n">r2</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>みたいなインスタンスを自動的に作ってくれる.これは,以下のかなり単純な規則で作られている:</p>
<ul class="simple">
<li>変換を適用する対象に適用する.</li>
<li><tt class="docutils literal">Functor</tt> のインスタンス部分には,変換を一般化して適用する.</li>
<li>それ以外の部分はそのまま出力する.</li>
</ul>
<p><tt class="docutils literal">DeriveFunctor</tt> という拡張があることから分かる通り, <tt class="docutils literal">Show</tt> や <tt class="docutils literal">Eq</tt> 並みに広い範囲に適用できるし, free functor というのも巷では流行っていて, <tt class="docutils literal">DeriveFunctor</tt> する代わりに同じ構造を無名で取り出すみたいなことができる.この free functor の売りが,「どんなデータ型でも <tt class="docutils literal">Functor</tt> にできる」だから, <tt class="docutils literal">Functor</tt> 制約がどれくらい無意味かは分かると思う.じゃあもう少し意味のある制約にできないだろうか?</p>
<p>例えば,単調性の保存も入れてみるとどうか? つまり,</p>
<div class="math block"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">{</mo><mi mathvariant="normal">∀</mi><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mi mathvariant="normal">.</mi><mtext> </mtext><mi>x</mi><mo>≤</mo><mi>y</mi><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>≤</mo><mi>f</mi><mo stretchy="false">(</mo><mi>y</mi><mo stretchy="false">)</mo><mo stretchy="false">}</mo><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mo stretchy="false">{</mo><mi mathvariant="normal">∀</mi><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mi mathvariant="normal">.</mi><mtext> </mtext><mi>x</mi><mo>≤</mo><mi>y</mi><mtext> </mtext><mo>⟹</mo><mtext> </mtext><mrow><mi mathvariant="normal">f</mi><mi mathvariant="normal">m</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">p</mi></mrow><mo stretchy="false">(</mo><mi>f</mi><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>≤</mo><mrow><mi mathvariant="normal">f</mi><mi mathvariant="normal">m</mi><mi mathvariant="normal">a</mi><mi mathvariant="normal">p</mi></mrow><mo stretchy="false">(</mo><mi>f</mi><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>y</mi><mo stretchy="false">)</mo><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">
\{\forall x, y.\, x \leq y \implies f(x) \leq f(y)\}
\implies \{\forall x, y.\, x \leq y \implies \mathrm{fmap}(f)(x) \leq \mathrm{fmap}(f)(y)\}
</annotation></semantics></math></span><span aria-hidden="true" class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7194em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7194em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">fmap</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">fmap</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)}</span></span></span></span></span></div>
<p>という法則を足す.これだと何が嬉しいかと言うと, <tt class="docutils literal">f :: Int <span class="pre">-></span> String = \n <span class="pre">-></span> replicate n 'a'</tt> に対し, <tt class="docutils literal">sort [fmap f n1, fmap f n2, <span class="pre">...]</span></tt> みたいなのを <tt class="docutils literal">[fmap f n | n <- sort [n1, n2, <span class="pre">...]]</span></tt> とすることができる.リストの比較より <tt class="docutils literal">Int</tt> の比較の方が効率がかなり良いことから,良い最適化になると考えられる.この法則を満たさないが,既存の <tt class="docutils literal">Functor</tt> になるインスタンスには次のものがある:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span>
<span class="normal">8</span></pre></div></td><td class="code"><div><pre><span></span><span class="kr">newtype</span><span class="w"> </span><span class="kt">Down</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Down</span><span class="w"> </span><span class="n">a</span>
<span class="w"> </span><span class="kr">deriving</span><span class="w"> </span><span class="kt">Eq</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Ord</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=></span><span class="w"> </span><span class="kt">Ord</span><span class="w"> </span><span class="p">(</span><span class="kt">Down</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">compare</span><span class="w"> </span><span class="p">(</span><span class="kt">Down</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Down</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">compare</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="n">x</span>
<span class="kr">instance</span><span class="w"> </span><span class="kt">Functor</span><span class="w"> </span><span class="kt">Down</span><span class="w"> </span><span class="kr">where</span>
<span class="w"> </span><span class="n">fmap</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">(</span><span class="kt">Down</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Down</span><span class="w"> </span><span class="p">(</span><span class="n">f</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>なのでちょっと微妙かもしれない.他には, <tt class="docutils literal">Foldable</tt> 的な方向性の拡張で, <tt class="docutils literal">fmap</tt> は再帰的にデータを辿る方法の 1 つというのも考えられるかもしれない.実際 <tt class="docutils literal">DeriveFoldable</tt> という拡張があるのだが,この実装方法は <tt class="docutils literal">DeriveFunctor</tt> と良く似ている.ただ,その場合もあんまり良く考えてないけど,作り方によってはインスタンスが複数あるみたいなことが起こりそうだ.</p>
<p><tt class="docutils literal">fmap</tt> が Haskell 界で広く用いられていることは,現状の <tt class="docutils literal">Functor</tt> クラスを支持する大きな根拠となる.ただ,制約として考えた場合にもっと意味のある区分を設けたいというのは自然なことだろう.その1つの方向性が, <tt class="docutils literal">Monad</tt> につながる, <tt class="docutils literal">m a</tt> を <tt class="docutils literal">a</tt> を一般化した高次のデータと見て, <tt class="docutils literal">m</tt> が付かない世界の計算を <tt class="docutils literal">m</tt> が付く世界にどれだけ持っていけるかを,制約として表すということだと思う.その点で, <tt class="docutils literal">fmap</tt> は <tt class="docutils literal">a</tt> の世界の計算を単純に <tt class="docutils literal">m</tt> が付く世界に持っていく, <tt class="docutils literal">Applicative</tt> / <tt class="docutils literal">Monad</tt> を前提とした見方で使う場合が多いと思う.本来ならその見方で使うのは <tt class="docutils literal">liftA</tt> とかなのかもしれない.</p>
<p>ただ単調性の保存の追加で挙げたように, <tt class="docutils literal">Functor</tt> から制約を作っていく方向性は <tt class="docutils literal">Monad</tt> だけではない.変換の一般化というのはもっと広い範囲で適用できて,というか出来すぎて,単体では意味がない場合が多い.でも逆に言えば,意味をかなり色んな方向から付与できる.その中でデータ型一般に適用できて,実装も単一に定まり,型クラスの仕様的にも表しやすい,最大公約数的な変換の一般化を表すクラスが,現状の <tt class="docutils literal">Functor</tt> だとも捉えられるかもしれない.そう考えると <tt class="docutils literal">Monad</tt> の見方で <tt class="docutils literal">fmap</tt> を使うのも約数的な使い方ということで,ある程度妥当とも言えるかもしれない.</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><tt class="docutils literal">Applicative</tt> が Haskell2020 に入りそうだったので,それを記念する意味も込めて (?) ,個人的な <tt class="docutils literal">Functor</tt> / <tt class="docutils literal">Applicative</tt> / <tt class="docutils literal">Monad</tt> の直感をまとめてみた.まあ,備忘録みたいな意味もあるかも.</p>
<p><tt class="docutils literal">Applicative</tt> が Haskell2020 に入って, no return プロポーサルも入り,治安が良くなってきそう <a class="footnote-reference" href="#ghc-status" id="auto-id-9">[4]</a> .なお, Haskell2020 が 2020 年に出るかどうかは 🙏</p>
<table class="docutils footnote" frame="void" id="slim-functor-law-by-free" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[1]</a></td><td><a class="reference external" href="https://www.schoolofhaskell.com/user/edwardk/snippets/fmap">https://www.schoolofhaskell.com/user/edwardk/snippets/fmap</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="amp-proposal-for-haskell2020" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[2]</a></td><td><a class="reference external" href="https://github.com/haskell/rfcs/pull/1">https://github.com/haskell/rfcs/pull/1</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="minimal-class-definition" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label">[3]</td><td><em>(<a class="fn-backref" href="#auto-id-3">1</a>, <a class="fn-backref" href="#auto-id-5">2</a>, <a class="fn-backref" href="#auto-id-6">3</a>)</em> なお,スペースと分かりやすさの都合上, minimal なメソッドだけを書くようにしている.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="ghc-status" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-9">[4]</a></td><td>GHC には既に入ってる.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/generalizing-transformation.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/generalizing-transformation.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>sitemap の追加2019-04-10T05:06:02+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-10:/blog/posts/2019/04/add-sitemap/<p>sitemap とかを追加してみたので,それの備忘録.</p>
<div class="section" id="auto-id-1">
<h2>sitemap 周辺ファイルの追加<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まず Pelican で sitemap を生成させる.これは <tt class="docutils literal">sitemap</tt> プラグインを追 …</p></div><p>sitemap とかを追加してみたので,それの備忘録.</p>
<div class="section" id="auto-id-1">
<h2>sitemap 周辺ファイルの追加<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まず Pelican で sitemap を生成させる.これは <tt class="docutils literal">sitemap</tt> プラグインを追加するだけでいい:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span></pre></div></td><td class="code"><div><pre><span></span><span class="w"> </span> PLUGINS = [
<span class="w"> </span> ...
<span class="gi">+ 'sitemap',</span>
<span class="w"> </span> ]
</pre></div></td></tr></table></div>
<p>後は <tt class="docutils literal">SITEMAP</tt> に設定を書く.以下の感じのことを書いた:</p>
<pre class="literal-block">
SITEMAP = {
'format': 'xml',
'priorities': {
'articles': 0.7,
'indexes': 0.5,
'pages': 0.6,
},
'changefreqs': {
'articles': 'monthly',
'indexes': 'daily',
'pages': 'monthly',
}
}
</pre>
<p>これで,ビルドすると <tt class="docutils literal">output/sitemap.xml</tt> が作成される.後は, <tt class="docutils literal">robots.txt</tt> で sitemap の場所を通知してやる. <tt class="docutils literal">robots.txt</tt> は直下に置かなければいけないので, <a class="reference external" href="https://github.com/mizunashi-mana/mizunashi-mana.github.io">https://github.com/mizunashi-mana/mizunashi-mana.github.io</a> の方に追加した.普通に以下の感じのことを書く:</p>
<pre class="literal-block">
User-agent: *
Disallow:
Allow:
Sitemap: https://mizunashi-mana.github.io/blog/sitemap.xml
</pre>
<p>これでおk.</p>
</div>
<div class="section" id="google-search-console">
<h2>Google Search Console の登録<a class="headerlink" href="#google-search-console" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>後 Google Search Console に登録する. Search Console のページに行って <a class="reference external" href="https://mizunashi-mana.github.io">https://mizunashi-mana.github.io</a> でプロパティを追加すると,所有の確認画面が出てくる.そのサイトを所有しているかの確認方法はいくつかあって,一番簡単なのは Google Analytics が既に導入されているならそれでやるのがいいっぽい.<a class="reference external" href="https://mizunashi-mana.github.io">https://mizunashi-mana.github.io</a> は Google Analytics は動いてないので,別の方法でやる必要がある.簡単なのは HTML タグに meta 情報を追加する方法だったけどなんかうまくいかなかったので, HTML ファイルを追加するやつを試した.</p>
<p>所有の確認画面から HTML ファイルをダウンロードしてその名前でアップロードするだけ.それで確認ボタンを押せばいける.ついでに, <tt class="docutils literal">robots.txt</tt> の更新リクエストも送っておく.これは, <a class="reference external" href="https://www.google.com/webmasters/tools/robots-testing-tool">robots.txt テスター</a> から行える.更新したいサイトを選んで,送信ボタンを押すと,更新される.後, sitemap の送信もしておく. Google Search Console の「インデックス」 > 「サイトマップ」に行って,画面に sitemap の URL を入力すればいい.後は数日待つ.</p>
<p>後, Google Analytics と Google Search Console を連携できるので,連携しておく. Google Analytics の集客メニューに Search Console ページへのリンクがあるので,それを踏んで Search Console のプロパティを対応づけする (どういうことやったのか忘れた) .</p>
<p>数日後には Google Search Console で色々な情報が見れるようになっている.なお,このページは検索対象にちゃんと含まれているのか? みたいな疑問があれば, URL 検査からチェックしてみるといい.そうすると, Google 検索のためにインデックスされているページ情報が見れる.</p>
</div>
<div class="section" id="auto-id-2">
<h2>まとめ<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>正直 SEO 対策しても改善に取り組む姿勢が僕に無いんで,グーグルに情報提供してるだけみたいにもなってるが,まあ何もしなくてもグーグルに情報行ってるんで多少はね? それにこういう系は見たいって思った時に導入して即見れるとかでは無いし,自分でやらないと知見溜まらないしね.たまには覗いていくか〜みたいな感じ.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/add-sitemap.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/add-sitemap.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>CTMCP のために Mozart/Oz を動かす2019-04-08T09:50:49+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-08:/blog/posts/2019/04/read-ctmcp/<p>ゼミの輪読で, <a class="reference external" href="https://www.amazon.co.jp/dp/0262220695">Concepts, Techniques, and Models of Computer Programming (MIT Press)</a> ,略称 CTM または CTMCP を読むことになった.その為の準備と,ちょっとだけ読んだのでそ …</p><p>ゼミの輪読で, <a class="reference external" href="https://www.amazon.co.jp/dp/0262220695">Concepts, Techniques, and Models of Computer Programming (MIT Press)</a> ,略称 CTM または CTMCP を読むことになった.その為の準備と,ちょっとだけ読んだのでそのまとめ.</p>
<div class="section" id="mozart-oz">
<h2>Mozart/Oz<a class="headerlink" href="#mozart-oz" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>この本では, Oz というプログラミング言語を扱っている.と言っても, Oz の実装である Mozart に完全に焦点を当てている. Oz 自体は名前を聞いたことはあったが今まで触ったことはなかった. <a class="reference external" href="https://mozart.github.io/mozart-v1/doc-1.4.0/tutorial/index.html">公式ドキュメント</a> によると</p>
<blockquote>
<p>"Oz is a multi-paradigm language that is designed for advanced, concurrent, networked, soft real-time, and reactive applications."</p>
<p>"Oz はマルチパラダイムな言語で,高度で,並行で,ネットワークを使用し,ソフトリアルタイム <a class="footnote-reference" href="#about-soft-realtime" id="auto-id-2">[1]</a> でリアクティブ <a class="footnote-reference" href="#about-reactive" id="auto-id-3">[2]</a> なアプリケーションのために設計されています."</p>
<p class="attribution">—Tutorial of Oz by Seif Haridi and Nils Franzén</p>
</blockquote>
<p>という言語らしい. Mozart は UCL の PLDC 研究グループによって開発が続けられている Oz の主要実装ということになる.</p>
<p>ところで, Mozart/Oz でググると一番最初に出てくる <a class="reference external" href="https://qiita.com/mshioda/items/9de1399db486107f1c30">「Mozart/Oz について話します」</a> という記事の中で述べられているように,あまり積極的な開発体制が整っているわけではないようだ.また,メジャーバージョン1から現在のメジャーバージョン2に移る時に,開発体制の大規模な移行があったのか,本書で出てくるサイト <a class="reference external" href="http://www.mozart-oz.org">http://www.mozart-oz.org</a> は稼働しておらず, <a class="reference external" href="https://mozart.github.io/">https://mozart.github.io/</a> の方に移っている.</p>
<p>ただ,開発自体は続いているようで,半年前ぐらいにメジャーバージョン2の初の安定板, <a class="reference external" href="https://github.com/mozart/mozart2/releases/tag/v2.0.1">2.0.1</a> がリリースされている.とりあえずこれをインストールしたが,今の所 (1章までしか読んでない) 本書のサンプルは問題なく動く.今後に期待という感じだろうか.</p>
</div>
<div class="section" id="auto-id-6">
<h2>Mozart/Oz の使い方<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まずは, Mozart をインストールして,動かしてみる.インストールは macOS で行ったので,他の環境でどうなるのかは分からないが,ひとまず <a class="reference external" href="https://github.com/mozart/mozart2/releases/tag/v2.0.1">リリースページ</a> をみる限り macOS / Debian / RedHat / Windows 向けのインストーラは提供されていそう.今回は,macOS 向けの <tt class="docutils literal"><span class="pre">mozart2-2.0.1-x86_64-darwin.dmg</span></tt> をダウンロードして起動した.で,アプリケーションフォルダに <tt class="docutils literal">Mozart2.app</tt> をインストールする.後 Emacs が必要なので, <a class="reference external" href="https://emacsformacosx.com/">https://emacsformacosx.com/</a> とかから適当に入れる.</p>
<p>で,起動すると以下の画面が出てくる:</p>
<img alt="上下に分かれた Emacs 画面が表示される." src="https://mizunashi-mana.github.io/blog/posts/2019/04/read-ctmcp/read-ctmcp/oz-emacs-screenshot.png"/>
<p>上のバッファがプログラミングする部分,下のバッファがコンパイラの出力画面になる.上のバッファで例えば次のようにプログラミングを行える.</p>
<img alt="``{Browse 42}`` と書くと 42 を表示するプログラムになる.コンパイルに成功し, accepted と表示されているのが分かる." src="https://mizunashi-mana.github.io/blog/posts/2019/04/read-ctmcp/read-ctmcp/oz-programming-sample.png"/>
<p>ここではプログラム <tt class="docutils literal">{Browse 42}</tt> をコンパイルしている.コンパイルは <tt class="docutils literal">Oz</tt> メニューの「Feed Buffer」という項目から行え, <tt class="docutils literal"><span class="pre">C-.</span> <span class="pre">C-b</span></tt> が割り当てられている.なおカーソル位置までを実行したかったら「Feed Region (<tt class="docutils literal"><span class="pre">C-.</span> <span class="pre">C-r</span></tt>) 」で行える.対話的なデバッグの際有用だ.「Feed Buffer」後はコンパイラの出力画面に accepted / rejected が表示され, accepted の場合今回の例だと,次のような出力ウィンドウが表示される:</p>
<img alt="42 と表示されたウィンドウが表示される." src="https://mizunashi-mana.github.io/blog/posts/2019/04/read-ctmcp/read-ctmcp/oz-output-screenshot.png"/>
<p>ついでに, Emacs のこの GUI でなく普通のプログラミングスタイルでやりたいなら, <tt class="docutils literal">/Applications/Mozart2.app/Contents/Resources/bin</tt> の中に色々ツールが入ってるのでそれを使う.例えば,簡単な Hello World プログラムは次のように作れる:</p>
<pre class="literal-block">
$ export PATH=$PATH:/Applications/Mozart2.app/Contents/Resources/bin
$ cat > helloworld.oz
functor
import
System
define
{System.showInfo "Hello World!"}
end
$ ozc -x helloworld.oz
$ ls
helloworld helloworld.oz
$ ozengine helloworld
Hello World!
</pre>
<p>CTMCP を読む分には, Emacs の実行環境で問題なさそうなので,僕はそれでやる.なお,本書で紹介されてる <tt class="docutils literal">oz</tt> コマンドでの起動はうまくいかなかった.なんでだろね. <tt class="docutils literal">Mozart2.app</tt> から起動すればいいので特に困ることはないんだけど.</p>
<p>後, <tt class="docutils literal">Browse</tt> で一々別のウィンドウが立ち上がるのがめんどいという人は, Oz Emulator というバッファが用意されているので,それを表示して, <tt class="docutils literal">Browse</tt> を適宜 <tt class="docutils literal">Show</tt> 関数に読み替えると良いっぽい.そうすると別ウィンドウが立ち上がる代わりに, Emulator の方に出力が表示される.僕は以下の画面構成で書いてる:</p>
<img alt="下の画面を分割して,左にコンパイラ出力,右にエミュレータ出力が見えるようにしている." src="https://mizunashi-mana.github.io/blog/posts/2019/04/read-ctmcp/read-ctmcp/oz-my-screen.png"/>
</div>
<div class="section" id="ctmcp-1">
<h2>CTMCP 1章の内容<a class="headerlink" href="#ctmcp-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>準備できたので,早速読んでいく.内容の詳細説明はしないので,内容が気になる方とか Oz の文法が知りたい方は普通に読んでくれ.</p>
<p>1章の内容は, Oz の説明と簡単な文法,それから取り入れられてる機能の説明っぽい.まあ概要だしね.これからやってく内容を,サンプルプログラムを元にちょっとずつ説明していく感じ.全くプログラミングをやったことない人にはきついが,どれかのプログラミング言語の入門書を読んだくらいのレベルなら読めそう.大体は以下の内容:</p>
<ol class="arabic simple">
<li>最初は簡単なプログラムから,ちょっと複雑なプログラムまで,徐々に Oz に慣らしていく.</li>
<li>プログラムの正しさの検証の話.<ul>
<li>数学的な推論に基づくプログラム検証の話.</li>
<li>目次を見る限り, 13 章でやるのかな? 後でやるとは言っているが,どれくらい後なのかは特に本文では言及されてない.</li>
</ul>
</li>
<li>計算の複雑性の話.<ul>
<li>主に,プログラムの計算量の話かな.</li>
<li>これも特に本文では述べられていないが, 3.5 とかで出てきてそう.</li>
</ul>
</li>
<li>遅延評価の話.<ul>
<li>2.0.1 では表示が本文と違うが,多分気にしちゃいけないやつ.</li>
<li>Oz は遅延評価関数がサポートされていて,それを使ってどういうことができるかという話.</li>
<li>これは, 4.5 に書いてあるのかな. 3.6 とかにもありそうだし飛び飛びって感じそう.</li>
</ul>
</li>
<li>高階プログラミングの話.<ul>
<li>関数を引数にとる高階関数を使ったプログラミングの話.</li>
<li>これは, 3.6 に説明があるのかな.</li>
</ul>
</li>
<li>並行性の話<ul>
<li>Oz は並行プログラミングがサポートされていて,それを使ってどういうことができるかの話.</li>
<li>これは, 4 / 5 あたりが主にこの内容になってそう.あと 8 もそうだしそこかしこに出てきそう.</li>
</ul>
</li>
<li>データフローの話<ul>
<li>Oz でサポートされている,データフローに基づく並行実行のアーキテクチャの説明.</li>
<li>これは, 4.2 / 4.9 とかなんかな.よく分からん.</li>
</ul>
</li>
<li>明示的状態の話<ul>
<li>Oz は可変な変数がサポートされていて,それを使ってどういうことができるかの話.</li>
<li>これも同じく後で詳しくやるって言って具体的な章番号は書いていないが,多分 6 がその内容っぽい.</li>
</ul>
</li>
<li>オブジェクトの話<ul>
<li>オブジェクト指向の話っぽい. Oz では,カプセル化ができるという話が出てくる.</li>
<li>てか,次で諸にオブジェクト指向の話が出てきた.</li>
</ul>
</li>
<li>クラスの話<ul>
<li>オブジェクトのクラスを, record と factory という機能を使って作れるよって話.</li>
<li>後,オブジェクト指向の用語の説明とかが書いてある.</li>
<li>何故かここでは,オブジェクト指向プログラミングは 7 章でやると書いてある.</li>
</ul>
</li>
<li>非決定性の話<ul>
<li>並行性と可変な変数による非決定性の話.</li>
<li>レースコンディションって怖いねって話.</li>
<li>これは, 4.7 とかなのかな.</li>
</ul>
</li>
<li>不可分性の話<ul>
<li>Oz は排他制御をサポートしていて,それを使ってどう言うことができるかの話.</li>
<li>これは, 8.3 っぽい.</li>
</ul>
</li>
</ol>
<p>後は,演習問題って感じ.まだ 1 章しか読んでなくて,目次だけ見て「ここに出てきそう」って言ってるので出現場所の精度は期待しないでくれ.</p>
<p>演習問題もざっと目を通したけど,自分で考えるための脚注みたいな感じだった.本文に書かれてないけど,考えておいた方がいいことを,答えを伏せて書くみたいな,行間を目に見える形にしたみたいな感じ.知識の確認にはあまり使えなそう.まあ今回はそこまでちゃんとした話ではなかったのもあるかもしれないけど.ただ,もしこの形式で演習問題が続くなら,最後に確認のためやるというよりは,それぞれの節を読んだら演習問題を見に行くぐらいの方が良さそう.</p>
</div>
<div class="section" id="auto-id-8">
<h2>まとめ<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>CTMCP を読むための準備とか諸々をした.トピックがかなり網羅的で面白そうではあるが,内容が古そうなのは気になる. Mozart 2.0.1 だと動かないサンプルとか出てこないか心配.頑張っていくか.なお,一応 1 章のまとめは書いたが,これ以降の章は多分特にまとめとか書かない気がする.今回は環境構築メモるついでって感じだし.というわけで,よろしく.</p>
<table class="docutils footnote" frame="void" id="about-soft-realtime" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td>ソフトリアルタイム (soft realtime) とは,制御工学の用語の一つで,リアルタイムシステムのクラスの 1 つを表す.リアルタイムシステムの中でも処理時間の期限に求める制約が一番緩いクラスで,処理時間の期限をすぎると徐々に処理結果の価値が下がっていくようなシステムのことを指す.プログラミング言語がそのようなアプリケーションに対応しているということはつまり,高度なスケジューリングシステムを備えていると言いたいのだと思う.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="about-reactive" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[2]</a></td><td>一口にリアクティブ (reactive) と言っても,正直システムによって定義はかなり異なるが,一般的にはユーザからの入力に対して即座に出力を返すようなシステムのことを指す.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/read-ctmcp.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/read-ctmcp.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Google Analytics の導入2019-04-08T03:33:29+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-08:/blog/posts/2019/04/add-google-analytics/<p>Google Analytics を導入したので,やったことをまとめた.</p>
<div class="section" id="id">
<h2>トラッキング ID の設定<a class="headerlink" href="#id" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>既に Analytics のアカウントは持っていたので,そのアカ …</p></div><p>Google Analytics を導入したので,やったことをまとめた.</p>
<div class="section" id="id">
<h2>トラッキング ID の設定<a class="headerlink" href="#id" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>既に Analytics のアカウントは持っていたので,そのアカウントのプロパティを追加してトラッキング ID を入手するだけ.以下の手順を行うだけだった:</p>
<ol class="arabic simple">
<li><a class="reference external" href="https://analytics.google.com/analytics">https://analytics.google.com/analytics</a> の管理ページ表示</li>
<li>「プロパティを作成」ボタンを押す.</li>
<li>プロパティの項目を埋めていく.大体以下の感じ:<ul>
<li>ウェブサイトの名前: GitHub Pages</li>
<li>ウェブサイトの URL: <a class="reference external" href="https://mizunashi-mana.github">https://mizunashi-mana.github</a></li>
<li>ウェブサイトの業種: その他<ul>
<li>なお,業種を設定すると目標テンプレートというものを利用できるらしい.詳細は, <a class="reference external" href="https://support.google.com/analytics/answer/1032415">https://support.google.com/analytics/answer/1032415</a> を参照.</li>
</ul>
</li>
<li>ウェブサイトのタイムゾーン: 日本 (+09:00)</li>
</ul>
</li>
<li>そうするとトラッキング ID のページに移動する.表示されているコードは無視して,トラッキング ID だけメモる.<ul>
<li>Pelican の Flex テーマが対応しているため,特にコードの埋め込みとかは必要ない.</li>
</ul>
</li>
</ol>
<p>後はメモった トラッキング ID を Pelican 側で設定するだけ. publish した時のみ設定されるよう <tt class="docutils literal">publichconf.py</tt> に以下を足す:</p>
<pre class="literal-block">
GOOGLE_ANALYTICS = "UA-XXXXXXXXX-X"
</pre>
<p>これで Google Analytics が動くようになる.</p>
</div>
<div class="section" id="auto-id-1">
<h2>プライバシーポリシーの変更<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Google Analytics の <a class="reference external" href="https://www.google.com/analytics/terms/jp.html">利用規約</a> には,「7. プライバシー」の節に以下のような定めがある.</p>
<ul class="simple">
<li>導入するサイトのプライバシーポリシーを公開すること.</li>
<li>プライバシーポリシーで,データ収集のため Cookie を使用していることを必ず通知すること.</li>
<li>プライバシーポリシーで,Google Analytics を使用していること及び Google Analytics でデータが収集、処理される仕組みについても必ず開示すること.これは, <a class="reference external" href="https://www.google.com/intl/ja/policies/privacy/partners/">https://www.google.com/intl/ja/policies/privacy/partners/</a> などのリンクを目立つように示すことで可能.</li>
</ul>
<p>事前に公開通知する旨も出していたので,それを実施する形で,プライバシーポリシーに以上の事柄に違反しないよう Google Analytics の説明を追加した.ついでに整形も行なった.差分は, <a class="reference external" href="https://github.com/mizunashi-mana/blog/pull/20/commits/8da9a0c91ee5d52e9d0fa62204adadede726493b#diff-ad32853aff6dff0fd8fb93798300aec0">https://github.com/mizunashi-mana/blog/pull/20/commits/8da9a0c91ee5d52e9d0fa62204adadede726493b#diff-ad32853aff6dff0fd8fb93798300aec0</a> から確認できる.</p>
</div>
<div class="section" id="auto-id-3">
<h2>まとめ<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Google Analytics をブログに導入した.後は,検索ワードとかを随時見ながら, Google Analytics の知見をためて,ブログを改善していけたらと思う.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/add-google-analytics.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/add-google-analytics.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>GHC のノートコメントについてのあれこれ2019-04-06T15:31:37+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-06:/blog/posts/2019/04/ghc-compiler-notes/<p><a class="reference external" href="https://github.com/myuon/ghc-compiler-notes">https://github.com/myuon/ghc-compiler-notes</a> にコントリビュートしたので,それについてと考えてることとか書く.</p>
<p>なお, myuon さんによる紹介記事も参照 …</p><p><a class="reference external" href="https://github.com/myuon/ghc-compiler-notes">https://github.com/myuon/ghc-compiler-notes</a> にコントリビュートしたので,それについてと考えてることとか書く.</p>
<p>なお, myuon さんによる紹介記事も参照: <a class="reference external" href="https://myuon.github.io/posts/ghc-compiler-notes/">https://myuon.github.io/posts/ghc-compiler-notes/</a></p>
<div class="section" id="auto-id-1">
<h2>GHC のノートコメント<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/wikis/commentary/coding-style#comments-in-the-source-code">GHC のコーディングガイド</a> にも書いてあるが, GHC では長いコメントを書くとき,以下のように主要部分を切り出す運用をしている:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span></pre></div></td><td class="code"><div><pre><span></span><span class="nf">someFunc</span><span class="w"> </span><span class="ow">=</span>
<span class="w"> </span><span class="kr">let</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">42</span><span class="w"> </span><span class="c1">-- See Note [The Answer To Life]</span>
<span class="w"> </span><span class="kr">in</span><span class="w"> </span><span class="n">v</span>
<span class="cm">{- Note [The Answer To Life]</span>
<span class="cm">~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span>
<span class="cm">"The Answer to the Ultimate Question of Life, the Universe, and Everything" is 42.</span>
<span class="cm">After seven and a half million years of calculation, deep thoughts finally output the answer.</span>
<span class="cm">-}</span>
</pre></div></td></tr></table></div>
<p>例えば, <a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/prelude/TysPrim.hs#L593">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/prelude/TysPrim.hs#L593</a> のような感じ.内容は,</p>
<ul class="simple">
<li>実装上の注意事項やアドバイス</li>
<li>形式的なアルゴリズムの説明</li>
<li>API の使い方や使われ方</li>
</ul>
<p>を含む色々. GHC 開発チーム向け以外にも, GHC で Haskell を書く上で重要なことが書いてある.例に挙げた type equality のまとめの他,</p>
<dl class="docutils">
<dt>The rules for map</dt>
<dd><p class="first"><tt class="docutils literal">map</tt> の <tt class="docutils literal">RULES</tt> がどういう挙動をするかの話</p>
<p class="last"><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/libraries/base/GHC/Base.hs#L1119">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/libraries/base/GHC/Base.hs#L1119</a></p>
</dd>
<dt>The oneShot function</dt>
<dd><p class="first"><tt class="docutils literal">oneShot</tt> 関数の概要</p>
<p class="last"><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/basicTypes/MkId.hs#L1473">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/basicTypes/MkId.hs#L1473</a></p>
</dd>
<dt>Call Arity: The goal</dt>
<dd><p class="first">call arity 解析の概要</p>
<p class="last"><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/simplCore/CallArity.hs#L35">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/simplCore/CallArity.hs#L35</a></p>
</dd>
<dt>Choosing loop breakers</dt>
<dd><p class="first">loop breaker をどのように選ぶかの話</p>
<p class="last"><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/simplCore/OccurAnal.hs#L279">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/simplCore/OccurAnal.hs#L279</a></p>
</dd>
<dt>Join points</dt>
<dd><p class="first">join points の概要</p>
<p class="last"><a class="reference external" href="https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/simplCore/FloatOut.hs#L112">https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/simplCore/FloatOut.hs#L112</a></p>
</dd>
</dl>
<p>など,より Haskell を理解する上で役に立つコメントも多い.</p>
</div>
<div class="section" id="ghc-compiler-notes">
<h2>GHC Compiler Notes<a class="headerlink" href="#ghc-compiler-notes" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>GHC のノートコメントは有用なことが書いてあり, GHC のリポジトリで管理されているためコードとの乖離も少ない.ただ,コードと一緒に書いてある分ノイズも多い. GHC の利用者としてはノートコメントだけを参照したい場合も多く,そこだけ抽出して見やすくできないかとは思っていた.で,半年前くらいに <a class="reference external" href="https://twitter.com/myuon_myon">myuon さん</a> と <a class="reference external" href="https://twitter.com/waddlaw">waddlaw</a> さんが,そういうプロジェクトを作っていると言う話を聞いて気になっていた.そのプロジェクトが上で挙げた <a class="reference external" href="https://github.com/myuon/ghc-compiler-notes">https://github.com/myuon/ghc-compiler-notes</a> になる.</p>
<p>でちょっと前にノートコメントを参照することがあって,どうせならそのプロジェクトを利用してみるかという感じだったんだが,作りかけで止まっていたっぽかった.やる気と時間があったのでひとまず,完成させてみることにした.最初は結構簡単にいくやろと思っていたが結構難しかった.内部の仕組みは主に,</p>
<ol class="arabic simple">
<li>GHC API を利用して Haskell コードをトークン解析する.</li>
<li>トークンをパースして,ノートコメントに分割する.</li>
<li>分割されたノートコメントを統合して, reStructuredText 形式で吐き出す (この辺結構怪しい)</li>
</ol>
<p>という感じ.手間がかかったのが GHC API を利用する部分で, <tt class="docutils literal">Show</tt> インスタンスがないデータを使わされたり, <tt class="docutils literal">DynFlags</tt> が色んなとこにでてきたり, lazy I/O を気にしなきゃいけなかったり, export されてない関数を使う必要があったり,まあ色々大変だった.特に今回これをやるまで分かってなかったんだけど, GHC は Haskell ファイルを大体以下の手順で解析するらしい.</p>
<ol class="arabic simple">
<li>Lexer をヘッド部分 <a class="footnote-reference" href="#get-options-range" id="auto-id-3">[1]</a> まで走らせ,<tt class="docutils literal">LANGUAGE</tt> プラグマや <tt class="docutils literal">OPTIONS_XXX</tt> プラグマを読み込む.</li>
<li><tt class="docutils literal">CPP</tt> 拡張が指定されていれば, <tt class="docutils literal">cpp</tt> を走らせる.</li>
<li>Lexer によるトークン解析をする.</li>
<li>トークンをパースして, AST に変換する <a class="footnote-reference" href="#parsing-hs" id="auto-id-4">[2]</a>.</li>
<li>後は色々する.</li>
</ol>
<p>後,通常 GHC はコメントを読み飛ばすが,</p>
<dl class="docutils">
<dt>Haddock モード</dt>
<dd>Haddock のドキュメントコメントを解析し,それもトークンに含める.</dd>
<dt>生のトークンを残すモード</dt>
<dd>本来なら削除するコメントトークンを,出力するトークンに含める.</dd>
</dl>
<p>という2つのモードも提供されている.今回はこのどちらもを使用した.トークンに分割した後は, <a class="reference external" href="https://github.com/myuon/ghc-compiler-notes/blob/master/doc/ParsingNotes.md">https://github.com/myuon/ghc-compiler-notes/blob/master/doc/ParsingNotes.md</a> に沿って大体 regular なパーシングをしていった.</p>
<p>最終的な成果物だが, PR を送った結果, myuon さんが解析結果をいい感じに整形するコードと Sphinx の設定を追加して Read the docs に上げてくれて,今は <a class="reference external" href="https://ghc-compiler-notes.readthedocs.io/en/latest/">https://ghc-compiler-notes.readthedocs.io/en/latest/</a> から見れるようになっている.検索もできるので,ぜひ参照してほしい.</p>
</div>
<div class="section" id="auto-id-5">
<h2>ノートコメントの文法<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ところでここからが本題なんだが,予想していたことではあるものの,解析は現状あまり上手くいっていない.ノートコメントの範囲を厳密に解析できていないのもそうなんだが,主に文法解釈が壊滅している. GHC のノートコメントは今まで何となく reStructuredText だと思っていたんだけど,少なくとも reStructuredText ではないっぽい.というか,何か形式化されている文法には則っていないんじゃないかと思っている.ちょっと調べた感じでは,この文法に従えというのは特に明記されておらず,事実ノートコメントは色んな文法に則って書かれている.</p>
<p>LaTeX の文法やHaskell Wiki の文法も度々散見されるが,多くはある一定の慣習 (これも時期と書く人によってかなりブレているんだが) に則って書かれてはいるようだ.</p>
<dl class="docutils">
<dt>Section</dt>
<dd><tt class="docutils literal"><span class="pre">*******</span></tt> で両側を囲んで,それをさらに <tt class="docutils literal">*</tt> で囲み,その内側に題を書く.</dd>
<dt>Sub section</dt>
<dd><tt class="docutils literal">-</tt> / <tt class="docutils literal">~</tt> などで下線を引く.</dd>
<dt>Code block</dt>
<dd>インデントする.</dd>
</dl>
<p>という感じだ.大体は reStructuredText より Markdown の文法に近いようであるが, <a class="reference external" href="https://daringfireball.net/projects/markdown/syntax">古典的な Markdown</a> では <tt class="docutils literal">~</tt> による下線を認めてない辺り,古き良き Markdown 寄り独自のマークアップの感じがする.この辺何か知っている人がいれば,色々教えてもらいたい.</p>
<p>さて,せっかく労力をかけたのにこのザマではちょっと悲しい.なので,この問題をなんとかする手を色々考え中だ.基本的な方針は変えようがなくて,「 GHC チームとコンタクトを取り, GHC のソースを修正する」だ.ただ,どのような提案をするかが問題になる.現状考えていることは,</p>
<ol class="arabic simple">
<li>形式的な仕様があるのか,形式的な仕様を策定 (既存のに乗っかる / 新たなマークアップ定義をする) しないかと提案する.<ul>
<li>特に,コードブロックと引用,サブコンテンツは区別してほしい.</li>
</ul>
</li>
<li>明らかな現状の間違い (下線がないノートコメント / コードブロック表記が独自) を修正するリクエストを投げる.</li>
<li>形式的な仕様が策定されたらそれに合わせて GHC Compiler Notes を修正.既存の GHC コードもちょっとずつ修正するリクエストを投げていく.</li>
</ol>
<p>という感じだ.これを Haskell Cafe か ghcdev のメーリングリストに投げてみようかなと考えている.気がかりなのは,これはあくまでプログラムによる自動解析のための修正だということだ.本来コメントは分かりやすさが正義だし,見栄えを気にするならそれこそ GHC Wiki に書くべきだろう.その辺の兼ね合いはどうなんだろうという気はしなくもない.</p>
<p>まあ,提案が reject されればそれはそれだし,とりあえず提案してみようかなという気にはなっている.</p>
</div>
<div class="section" id="auto-id-6">
<h2>まとめ<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>というわけで, GHC Compiler Notes にコントリビュートして,あれこれ考えた話を書いた.時間があれば,提案の文面考えて適当に投げていきたい.以上.</p>
<table class="docutils footnote" frame="void" id="get-options-range" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-3">[1]</a></td><td>ほぼ <tt class="docutils literal">module</tt> キーワードまでと思って良い.厳密には, <tt class="docutils literal">CPP</tt> とかが入ったりすると違ったりするんだが.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="parsing-hs" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-4">[2]</a></td><td>この時完全に構文が解析されるわけではなくて,演算子の優先順位の解決とかはリネーム時に行われる.</td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/ghc-compiler-notes.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/ghc-compiler-notes.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>ブログに共有ボタンを追加した2019-04-04T18:51:33+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-04:/blog/posts/2019/04/add-share-button/<p>ブログに共有ボタンを追加して, JavaScript を呼べるようにした.</p>
<div class="section" id="auto-id-2">
<h2>導入までの経緯<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Pelican には CSS を追加する仕組みはあるが, JavaScript を追 …</p></div><p>ブログに共有ボタンを追加して, JavaScript を呼べるようにした.</p>
<div class="section" id="auto-id-2">
<h2>導入までの経緯<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Pelican には CSS を追加する仕組みはあるが, JavaScript を追加する仕組みはない.なので,テーマで対応していない JavaScript を使う機能は入れられない.これでは不便なので, JavaScript を無理やり追加することにした.</p>
<p>また,共有ボタンも現状テーマで対応していないため,無理やり JavaScript で追加することにした.静的に埋め込むこともできるのだが,どうせ JavaScript の機能が必要になる共有ボタンもあるので, JavaScript 有効下のみ共有ボタンが表示されることになっても問題ないであろう.しかも,共有ボタンの位置も下の方に設置することにしたので,読み込みの遅延をあまり感じることもないだろう.</p>
<p>で,結構色々大変だったので,記事にまとめておくことにした.</p>
</div>
<div class="section" id="pelican">
<h2>Pelican のプラグイン追加<a class="headerlink" href="#pelican" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まず,ブログ独自のプラグインを作って,そのプラグインで JavaScript を埋め込むことにした.</p>
<p>プラグインの作り方は, <a class="reference external" href="https://docs.getpelican.com/en/stable/plugins.html#how-to-create-plugins">https://docs.getpelican.com/en/stable/plugins.html#how-to-create-plugins</a> を見れば概要は載ってるが,正直分からない.基本的には, <tt class="docutils literal">signals</tt> をインポートして, <tt class="docutils literal">register</tt> 関数でフックしたいイベントを登録する.イベントが呼ばれる位置は, Pelican のソースを見るしかない.そして見ても分からない.</p>
<p>しょうがないので, <a class="reference external" href="https://docs.getpelican.com/en/stable/plugins.html#how-to-create-plugins">プラグインのソース</a> を見ながらニュアンスでやっていくしかない.とりあえず, <a class="reference external" href="https://github.com/getpelican/pelican-plugins/blob/master/better_tables/better_tables.py">better_tables プラグインのソース</a> を見てみると, <tt class="docutils literal">content_object_init</tt> をフックするとそれぞれのページ内容がレンダリングされた HTML を弄れることが分かる.主に,</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span></pre></div></td><td class="code"><div><pre><span></span><span class="k">def</span> <span class="nf">convert_content</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
<span class="n">content</span><span class="o">.</span><span class="n">_content</span> <span class="o">=</span> <span class="n">some_process</span><span class="p">(</span><span class="n">content</span><span class="o">.</span><span class="n">_content</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">register</span><span class="p">():</span>
<span class="n">signals</span><span class="o">.</span><span class="n">content_object_init</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">convert_content</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>的なことを書くと,それぞれのページ内容に対して <tt class="docutils literal">convert_content</tt> が呼ばれ, <tt class="docutils literal">content._content</tt> にレンダリングされた内容が文字列で入っているためそれを弄ることができるようだ.気をつけて欲しいのは,レンダリングされた内容はあくまで reStructuredText などを HTML に変換した内容であってそれぞれのテーマの全 HTML がとれるわけではないことだ.</p>
<p>今回はこの <tt class="docutils literal">content_object_init</tt> を使って適当に HTML を BeautifulSoup を使ってパースし,最後の方にページのメタ情報と JavaScript ファイルを埋め込んでいる.かなり雑だがソースは, <a class="reference external" href="https://github.com/mizunashi-mana/blog/tree/master/plugins/custom/embed_customjs">https://github.com/mizunashi-mana/blog/tree/master/plugins/custom/embed_customjs</a> から見れる. <tt class="docutils literal">pelicanconf.py</tt> に <tt class="docutils literal">JS_FILE</tt> で埋め込みたい JavaScript ファイルを指定するとそのファイルを埋め込むようになっている.あと,ページ内容ごとのメタデータを埋め込んでいる.</p>
</div>
<div class="section" id="js">
<h2>共有ボタン追加の JS コード<a class="headerlink" href="#js" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>後は共有ボタン追加の JavaScript を書くだけだ.まず適当に webpack の設定を以下のように書いた</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span>
<span class="normal">16</span>
<span class="normal">17</span>
<span class="normal">18</span>
<span class="normal">19</span>
<span class="normal">20</span>
<span class="normal">21</span>
<span class="normal">22</span>
<span class="normal">23</span>
<span class="normal">24</span>
<span class="normal">25</span>
<span class="normal">26</span></pre></div></td><td class="code"><div><pre><span></span><span class="kd">const</span><span class="w"> </span><span class="nx">webpack</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">require</span><span class="p">(</span><span class="s1">'webpack'</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">require</span><span class="p">(</span><span class="s1">'path'</span><span class="p">);</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="s1">'production'</span><span class="p">,</span>
<span class="w"> </span><span class="nx">entry</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">bundle</span><span class="o">:</span><span class="w"> </span><span class="s1">'./js/index.js'</span><span class="p">,</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">output</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">filename</span><span class="o">:</span><span class="w"> </span><span class="s1">'[name].js'</span><span class="p">,</span>
<span class="w"> </span><span class="nx">path</span><span class="o">:</span><span class="w"> </span><span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span><span class="w"> </span><span class="s1">'content/dist-asset'</span><span class="p">)</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">resolve</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">alias</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">vue$</span><span class="o">:</span><span class="w"> </span><span class="s1">'vue/dist/vue.esm.js'</span><span class="p">,</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">performance</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">maxEntrypointSize</span><span class="o">:</span><span class="w"> </span><span class="mf">400</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span>
<span class="w"> </span><span class="nx">maxAssetSize</span><span class="o">:</span><span class="w"> </span><span class="mf">400</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">1024</span><span class="p">,</span>
<span class="w"> </span><span class="p">},</span>
<span class="p">};</span>
</pre></div></td></tr></table></div>
<p>バンドル後のスクリプトは vue を埋め込むと webpack 標準のサイズ上限を超えるので,適当に増やす.後,必要なものをインストールする:</p>
<pre class="literal-block">
npm init # 質問にいい感じに答える
npm install -D webpack webpack-cli
npm install -S vue
</pre>
<p>後は, DOM の読み込みイベントにリスナー追加して,そこで共有ボタンの DOM を追加するコードを走らせる. DOM は Vue.js で生成して追加.コードは, <a class="reference external" href="https://github.com/mizunashi-mana/blog/blob/master/js/add_sharebuttons.js">https://github.com/mizunashi-mana/blog/blob/master/js/add_sharebuttons.js</a> においてある.まあなんてことはない Vue のコードです,はい.</p>
<p>生成したコードは, Flex テーマの <a class="reference external" href="https://github.com/alexandrevicenzi/Flex/blob/v2.2.0/templates/base.html#L122">Social の部分</a> を借りた.と言っても微調整は必要で,デザインをちょっちいじった.</p>
</div>
<div class="section" id="auto-id-4">
<h2>まとめ<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ドキュメントがあまりない分野をいじるのはしんどかった.まあしゃあないね.</p>
<p>JavaScript を任意に追加できるようになったので,数式環境を KaTeX でやるやつとかも近いうちにやりたい.ただ, KaTeX サポートは実はテーマの方でやってもらう方が良いのでは? とも思っている.一度導入してみて,それを切り出して Flex テーマの方に PR 送ろうかな.</p>
<p>てことで,今回は以上.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/add-share-button.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/add-share-button.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>Python の datetime が難しい2019-04-03T14:34:50+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-03:/blog/posts/2019/04/python-datetime/<p>色々ハマったので,メモをしておく.</p>
<div class="section" id="aware-naive">
<h2>aware と naive<a class="headerlink" href="#aware-naive" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Python の <tt class="docutils literal">datetime</tt> モジュールでは,日付情報を表現する <tt class="docutils literal">date</tt> オブジェクト,日中時間を表現する <tt class="docutils literal">time</tt> オブ …</p></div><p>色々ハマったので,メモをしておく.</p>
<div class="section" id="aware-naive">
<h2>aware と naive<a class="headerlink" href="#aware-naive" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>Python の <tt class="docutils literal">datetime</tt> モジュールでは,日付情報を表現する <tt class="docutils literal">date</tt> オブジェクト,日中時間を表現する <tt class="docutils literal">time</tt> オブジェクト,そしてその両方の組である <tt class="docutils literal">datetime</tt> オブジェクトが提供されている.そして,実は <tt class="docutils literal">datetime</tt> オブジェクトは2種類ある.この扱いの差が分からなくてまずつまづいてた.</p>
<p>そもそもドキュメントをちゃんと読めという話なんだけど, <a class="reference external" href="https://docs.python.org/ja/3/library/datetime.html">https://docs.python.org/ja/3/library/datetime.html</a> で普通に説明されている.端的に言えば,</p>
<ul class="simple">
<li>aware: 実時刻を表し,タイムゾーンや夏時間情報を持つ.</li>
<li>naive: 時刻情報だけを表現する.タイムゾーンなどの情報は持たず,その時刻がどういう意味を持つかは処理する側に委ねられる.</li>
</ul>
<p>の2種類があるらしい. aware か naive かは, <tt class="docutils literal">tzinfo</tt> プロパティが <tt class="docutils literal">None</tt> かどうかで判定できる. <tt class="docutils literal">None</tt> なら naive になる.ところで,ほとんどの場合 <tt class="docutils literal">datetime</tt> モジュールの API は naive なオブジェクトを製造する. <tt class="docutils literal">datetime.datetime.now()</tt> でさえ naive な <tt class="docutils literal">datetime</tt> オブジェクトを返す. aware なオブジェクトを取得したい場合明確にタイムゾーン情報を指定する必要がある.例えば,現在時刻を UTC で取得したい場合, <tt class="docutils literal">datetime.datetime.utcnow()</tt> ではなく, <tt class="docutils literal">datetime.datetime.now(datetime.timezone.utc)</tt> と書く.前者は naive なオブジェクトになり,後者は aware なオブジェクトになる.</p>
</div>
<div class="section" id="aware-naive-tzinfo">
<h2>aware / naive の相互変換と tzinfo<a class="headerlink" href="#aware-naive-tzinfo" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>それぞれのオブジェクトの相互変換は, <tt class="docutils literal">replace</tt> を使うことで以下のように可能:</p>
<pre class="literal-block">
def aware_to_naive(d):
return d.replace(tzinfo=None)
def naive_to_aware(d, tzinfo):
return d.replace(tzinfo=tzinfo)
</pre>
<p>3.5 までは, naive と aware の区別はかなり厳密で,例えば <tt class="docutils literal">astimezone</tt> は naive に対しては呼べなかった.これは, 3.6 で実行環境のローカルなタイムゾーンによる時刻だと解釈して呼ばれるよう変更されている.</p>
<p>なお,呼び方によって naive と aware のどちらが返ってくるかが別れる API も幾つかある. <tt class="docutils literal">strptime</tt> はタイムゾーン指定があると aware なオブジェクトを返し,ないと naive なオブジェクトを返す:</p>
<pre class="literal-block">
>>> datetime.datetime.strptime('2019-01-01T00:00:00Z', '%Y-%m-%dT%H:%M:%S%z')
datetime.datetime(2019, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
>>> datetime.datetime.strptime('2019-01-01T00:00:00', '%Y-%m-%dT%H:%M:%S')
datetime.datetime(2019, 1, 1, 0, 0)
</pre>
<p>ロケール込みの情報としてパースしたい場合,タイムゾーン情報を明示的に付与して aware に変換する必要がある:</p>
<pre class="literal-block">
>>> datetime.datetime.strptime('2019-01-01T00:00:00', '%Y-%m-%dT%H:%M:%S') \
... .replace(tzinfo=datetime.timezone.utc)
datetime.datetime(2019, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)
</pre>
<p><tt class="docutils literal">tzinfo</tt> は抽象クラスになっていて,自分でカスタムしたオブジェクトを作れるようになっている.標準的にはタイムゾーン情報を元にした <tt class="docutils literal">tzinfo</tt> オブジェクトの実装を提供する <tt class="docutils literal">timezone</tt> クラスを使っておけば問題ない. <tt class="docutils literal">timezone</tt> オブジェクトは UTC からの時間差から作成できる:</p>
<pre class="literal-block">
>>> datetime.datetime.strptime('2019-01-01T00:00:00', '%Y-%m-%dT%H:%M:%S') \
... .replace(tzinfo=datetime.timezone(datetime.timedelta(hours=9)))
datetime.datetime(2019, 1, 1, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(seconds=32400)))
</pre>
</div>
<div class="section" id="auto-id-1">
<h2>まとめ<a class="headerlink" href="#auto-id-1" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ちゃんとドキュメントは読もうと思いました (まる) . <tt class="docutils literal">datetime</tt> モジュール, 3.5 - 3.7 の間に結構変わってて厳しい気持ちになる. <tt class="docutils literal">fromisoformat</tt> が使えるのは 3.7 からだし, <tt class="docutils literal">strptime</tt> の <tt class="docutils literal">%Z</tt> で「:」付きの表現をパースしてくれるのも 3.7 からっぽい.</p>
<p>世の中は厳しいなあって感じでした.</p>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/python-datetime.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/python-datetime.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>ブログのデザイン調整2019-04-01T21:17:35+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-04-01:/blog/posts/2019/04/fix-blog-config/<p>ブログの改良をちょっと色々やってたので,そのご報告.</p>
<div class="section" id="circle-ci">
<h2>Circle CI での謎の警告解消<a class="headerlink" href="#circle-ci" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今まで Circle CI 上だと以下の警告が出てた:</p>
<pre class="literal-block">
WARNING: Locale could not be …</pre></div><p>ブログの改良をちょっと色々やってたので,そのご報告.</p>
<div class="section" id="circle-ci">
<h2>Circle CI での謎の警告解消<a class="headerlink" href="#circle-ci" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>今まで Circle CI 上だと以下の警告が出てた:</p>
<pre class="literal-block">
WARNING: Locale could not be set. Check the LOCALE setting, ensuring it is valid and available on your system.
</pre>
<p>ビルド自体は問題ないんだけど,気になるので修正したいなあと思ってた.</p>
<p>この警告は Pelican が出してるもので,以下が該当部分:</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal"> 1</span>
<span class="normal"> 2</span>
<span class="normal"> 3</span>
<span class="normal"> 4</span>
<span class="normal"> 5</span>
<span class="normal"> 6</span>
<span class="normal"> 7</span>
<span class="normal"> 8</span>
<span class="normal"> 9</span>
<span class="normal">10</span>
<span class="normal">11</span>
<span class="normal">12</span>
<span class="normal">13</span>
<span class="normal">14</span>
<span class="normal">15</span></pre></div></td><td class="code"><div><pre><span></span><span class="c1"># https://github.com/getpelican/pelican/blob/4.0.1/pelican/settings.py#L500</span>
<span class="c1"># try to set the different locales, fallback on the default.</span>
<span class="n">locales</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'LOCALE'</span><span class="p">,</span> <span class="n">DEFAULT_CONFIG</span><span class="p">[</span><span class="s1">'LOCALE'</span><span class="p">])</span>
<span class="k">for</span> <span class="n">locale_</span> <span class="ow">in</span> <span class="n">locales</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">locale</span><span class="o">.</span><span class="n">setlocale</span><span class="p">(</span><span class="n">locale</span><span class="o">.</span><span class="n">LC_ALL</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">locale_</span><span class="p">))</span>
<span class="k">break</span> <span class="c1"># break if it is successful</span>
<span class="k">except</span> <span class="n">locale</span><span class="o">.</span><span class="n">Error</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
<span class="s2">"Locale could not be set. Check the LOCALE setting, ensuring it "</span>
<span class="s2">"is valid and available on your system."</span><span class="p">)</span>
</pre></div></td></tr></table></div>
<p>どうやら <tt class="docutils literal">locale.setlocale</tt> が <tt class="docutils literal">ja_JP</tt> を設定しようとするとエラーを出してるっぽい.</p>
<p>Circle CI の良いところは Docker イメージをそのまま使ってくれるのでエラーの特定が楽ってところ.
というわけで,実際にどういうエラーを吐いて警告が出るに至ってるのか, Docker で調べてみた:</p>
<pre class="literal-block">
$ docker run -it circleci/python:3.7 bash
circleci:/$ python -c 'import locale; locale.setlocale(locale.LC_ALL, "ja_JP")'
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/local/lib/python3.7/locale.py", line 604, in setlocale
return _setlocale(category, locale)
locale.Error: unsupported locale setting
</pre>
<p>てことで, <tt class="docutils literal">locale.setlocale</tt> が失敗してるって時点で何となく予想はついてたけど, <tt class="docutils literal">ja_JP</tt> のロケール情報がインストールされてないのが問題っぽい.そこまでは予想がついたんだけど,じゃあ具体的にどう対処すればいいんだろうってとこがちょっと分からなくて,色々調べた.</p>
<p>Circle CI は通常 Debian を使ってるっぽい.一応 Debian であることを明示する為, <tt class="docutils literal"><span class="pre">-stretch</span></tt> とかいう接尾辞が付けられるっぽいので付けといた <a class="footnote-reference" href="#circleci-python-images" id="auto-id-2">[1]</a>. 現在インストールされてるロケールは, <tt class="docutils literal">locale</tt> コマンドで調べられるらしい:</p>
<pre class="literal-block">
circleci:/$ locale -a
C
C.UTF-8
POSIX
</pre>
<p>ここに <tt class="docutils literal">ja_JP</tt> が表示されれば勝ち.でロケールをインストールするには,インストールしたいロケールを <tt class="docutils literal">/etc/locale.gen</tt> で見つけてそこのコメントを外し, <tt class="docutils literal"><span class="pre">locale-gen</span></tt> コマンドを走らせるか, <tt class="docutils literal"><span class="pre">dpkg-reconfigure</span> locales</tt> をすればいいらしい.なので,以下のコマンドを Circle CI の設定に追加した:</p>
<pre class="literal-block">
sudo sed -i 's/# ja_JP\.UTF-8/ja_JP\.UTF-8/' /etc/locale.gen
sudo update-locale LANG=C.UTF-8 LC_MESSAGES=POSIX
DEBIAN_FRONTEND=noninteractive sudo -E dpkg-reconfigure locales
</pre>
<p>これで完璧やろw とか思ってプッシュしたがなんかエラーが治らない.試しに Docker 上でやってみると,以下のようになった:</p>
<pre class="literal-block">
circleci:/$ locale -a
C
C.UTF-8
POSIX
ja_JP.utf8
</pre>
<p>は? <tt class="docutils literal">ja_JP.utf8</tt> だけしか追加されとらんやんけ.どういうこっちゃって感じ.でさらに調べると,どうやら,ロケールのエイリアス情報が <tt class="docutils literal">/usr/share/locale/locale.alias</tt> って場所にあるらしく,ロケールのインストールの時はそこの名前も登録されるらしい.で,そこを見てみると,以下のようになってた:</p>
<pre class="literal-block">
circleci:/$ cat /usr/share/locale/locale.alias | grep ja_JP
japanese ja_JP.eucJP
japanese.euc ja_JP.eucJP
ja_JP ja_JP.eucJP
ja_JP.ujis ja_JP.eucJP
japanese.sjis ja_JP.SJIS
</pre>
<p>あ,ふーん.今は2019年, UTF-8 標準の時代やぞ.というわけで閉廷した.と言いたいとこだが,閉廷しても警告は治らないので,以下のコマンドを追加することにした:</p>
<pre class="literal-block">
sudo sed -i 's/ja_JP\s.*$/ja_JP ja_JP.utf8/g' /usr/share/locale/locale.alias
</pre>
<p>本来は Pelican の設定を変えるか, <tt class="docutils literal">ja_JP.eucJP</tt> を使うべきなんだろうが,ロケール情報は <tt class="docutils literal">gettext</tt> も使うと思われるのでマップ情報があるのは好ましくないだろうし,かといって eucJP を使うのは敗北感が強かったので間をとって(?)こうした.これにより,ちゃんとロケールが認識されるようになった:</p>
<pre class="literal-block">
circleci:/$ locale -a
C
C.UTF-8
POSIX
ja_JP
ja_JP.utf8
</pre>
<p>ついでに, cache のバージョニングもするようにして,壊れた cache が生成された時にバージョンを上げることで古いキャッシュを捨てられるようにした.</p>
</div>
<div class="section" id="auto-id-3">
<h2>アンカーリンクの追加<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>各節に飛ぶリンクを表示するようにした.これは, <a class="reference external" href="https://github.com/getpelican/pelican-plugins/tree/master/headerid">headerid</a> というプラグインがありこれを使った.単に <tt class="docutils literal">pelicanconf.py</tt> に</p>
<pre class="literal-block">
HEADERID_LINK_CHAR = '<i class="fas fa-link anchor-link"></i>'
</pre>
<p>を足して,ちょっとデザインとかをいじっただけ.</p>
<p>(ところで幾つかプラグインの実装を見てたんだけど,みんな HTML を Beautiful Soup でパースしてゴリ押ししてたりするんだが,大丈夫なんか... こういうもんなんだろうか...)</p>
</div>
<div class="section" id="vscode">
<h2>VSCode のプラグインの修正<a class="headerlink" href="#vscode" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><a class="reference external" href="https://mizunashi-mana.github.io/blog/posts/2019/03/start-blog/#auto-id-10">前の記事</a> で言ってた, reStructuredText の VSCode プラグインのバグを修正した: <a class="reference external" href="https://github.com/vscode-restructuredtext/vscode-restructuredtext/pull/153">https://github.com/vscode-restructuredtext/vscode-restructuredtext/pull/153</a> .</p>
<p>内容は, <tt class="docutils literal">docutils</tt> の <tt class="docutils literal">column_width <span class="pre"><https://sourceforge.net/p/docutils/code/HEAD/tree/tags/docutils-0.14/docutils/utils/__init__.py#l643></span></tt> 関数に合わせて下線の長さを修正するだけなんだけど,思ったより難しかった.</p>
<p>最近は,文字コードの世界は Unicode という規格で統一されつつあるわけだけど,この規格が結構罠が多い (正確には文字の世界は複雑すぎるということなんだけど) .で,よく槍玉に上がるのが</p>
<dl class="docutils">
<dt>East Asian Width</dt>
<dd><a class="reference external" href="https://www.unicode.org/reports/tr11/">https://www.unicode.org/reports/tr11/</a> で規定されている,文字幅の参考特性.半角とか全角とか,半角相当・全角相当みたいな感じのクラス分けをしている. (ただこの特性値自体も罠がある <a class="footnote-reference" href="#eaw-problem" id="auto-id-5">[2]</a>)</dd>
<dt>Combining Character</dt>
<dd>「ă」は2文字 U+0074 U+0306 で表現される.このうちの後ろの文字 U+0306 が Combining Character と呼ばれるもので,前後の文字にかかったり,異次元に飛んでったりして,単体ではあまり意味を持たないやつ.日本人的には濁点が一番親しみやすそう. Unicode のデータベースでは Combining class というパラメータが提供されていて,どういう Combining を行うかが分かるようになっている. 0 だと Combining Character ではない.それぞれの値の意味は, <a class="reference external" href="http://www.unicode.org/reports/tr44/#Canonical_Combining_Class_Values">http://www.unicode.org/reports/tr44/#Canonical_Combining_Class_Values</a> を参照.</dd>
<dt>Surrogate Pair</dt>
<dd><p class="first">UTF-16 という Unicode のエンコード方式が,世界の文字の固定サイズ表現を目指して大敗北した話は有名だけど,大敗北の余波を自分たちが存分に受けてることを知らない人は結構多い. JavaScript という言語は諸にこの余波を受けている. JavaScript の文字列の内部は 16bit 非負整数の配列だ.これだけだと他の言語も事情が同じものが多いわけだけど,問題は 文字列の長さ = <tt class="docutils literal">String.prototype.length</tt> が返してくる数値 = 配列の長さ と規定してしまった点だ.実際には Unicode 規格に含まれる文字は 16bit などでは納まりきらず, 16bit 2つを組み合わせて1つの文字を表す表現を併用することとなった.この組が Surrogate Pair だ.もし文字列の長さを「Unicodeにおける文字単位でいくつ分か」として取得したいなら, <tt class="docutils literal"><span class="pre">'おすし🍣'.length</span></tt> としてはいけない.「🍣」は Surrogate Pair で表現される文字で,この結果は</p>
<pre class="literal-block">
'おすし🍣'.length == 5
</pre>
<p>となる.最近の JavaScript での Surrogate Pair を考慮する場合のイディオムは,</p>
<pre class="literal-block">
[...'おすし🍣'].length == 4
</pre>
<p class="last">だ.文字列のイテレータは,Unicode 単位で文字を分解してくれるようになっているので,こちらだと Surrogate Pair に関する問題は起きない.</p>
</dd>
</dl>
<p>それぞれの特性規定自体は,そこまで大きな問題は孕んでいないと思う (詳しくないので知らない) けど,問題はこれらが日々アルファベット以外の文字を扱う人たちの間でしか発現しないこと,そして結果実装者が規格の存在を知っているかによって実装が大きく異なることであり,それによって実装の差異を吸収するための規格が実装によって大きな差異を生み出してしまうことにある.この辺の話は詳しい人に聞くと (外野から見てる分には) 中々面白いが,僕はあまり知識も経験もないのでここら辺でやめとく.ついでに今回は,この三つの役満だった.</p>
<p><tt class="docutils literal">docutils</tt> の <a class="reference external" href="https://sourceforge.net/p/docutils/code/HEAD/tree/tags/docutils-0.14/docutils/utils/__init__.py#l643">実装</a> は East Asian Width と Combining Character を考慮した実装になっていて, East Asian Width での文字の長さを換算した後, Combining Character の分を差し引いて,最終結果を出している.それに対して,プラグインの実装は単に <tt class="docutils literal">length</tt> で長さを計っていた.</p>
<p>これを, <a class="reference external" href="https://github.com/susisu/meaw">meaw</a> というライブラリのお世話になって修正した. <tt class="docutils literal">meaw.computeWidth</tt> という関数は <tt class="docutils literal">for</tt>-<tt class="docutils literal">of</tt> で文字列の文字それぞれの East Asian Width を合計してくれる. <tt class="docutils literal">for</tt>-<tt class="docutils literal">of</tt> は文字列のイテレータで要素を回すため, spread operator を使う場合と同じく Unicode 単位で文字を分解してくれる.</p>
<p>Combining Character に関しては,色々調べたんだけど,文字を与えると Unicode データベースを単に返してくれるライブラリが見つからなかったので断念した (この辺はライブラリの大きさとのトレードオフなので仕方ないとも思うがうーんって感じ. Python は標準サポートが入っていて強いなあって思った.) .なんかいい感じの方法知ってたら教えてもらいたい.ただ,下線は長い分には問題ないので,そこまで影響はないはず.一応, <tt class="docutils literal">normalize</tt> で1つの文字にまとめられる系はまとめるようにしておいたし.</p>
<p>もう既に修正は取り込まれてるので,時期バージョンで治るのかな?</p>
</div>
<div class="section" id="auto-id-7">
<h2>プライバシーポリシーの変更<a class="headerlink" href="#auto-id-7" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ちょこっと修正した.個人情報は匿名化されるって言ってたけど, Google Analytics とか GitHub Pages とかは中で何やってるか分からないので,そっちでは特定とかやってるかもしれない的なことを足した.</p>
<p>特定しても個人的には特にメリットがないので,うちはしないです.</p>
</div>
<div class="section" id="auto-id-8">
<h2>シェアボタンの追加のための調査<a class="headerlink" href="#auto-id-8" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>シェアボタンを追加したくて色々調査してた.最終的には, JavaScript でシェアボタン追加すればよくねってなったんだけど,そもそも自前の JavaScript を呼ぶ機構がテーマになさそう.プラグインでがんばって挿入とかできないかなとか試したけどよく分からんかった.</p>
<p>なので,もうちょっと後になりそう.</p>
</div>
<div class="section" id="auto-id-9">
<h2>今後について<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>ちょっと最近忙しいので,次の記事投稿まで期間開くかもだけど,落ち着いたら色々書くかも.こちらからは,以上です.</p>
<table class="docutils footnote" frame="void" id="circleci-python-images" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-2">[1]</a></td><td><a class="reference external" href="https://circleci.com/docs/2.0/circleci-images/#python">https://circleci.com/docs/2.0/circleci-images/#python</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="eaw-problem" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-5">[2]</a></td><td><a class="reference external" href="https://github.com/hamano/locale-eaw">https://github.com/hamano/locale-eaw</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/04/fix-blog-config.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/04/fix-blog-config.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>ブログ始めました2019-03-31T14:00:38+09:002020-03-29T08:23:18+09:00Mizunashi Manatag:mizunashi-mana.github.io,2019-03-31:/blog/posts/2019/03/start-blog/<p>色々あって,技術的なことを書くブログを始めようと思いました (まる) .
今までは, Advent Calendar の時期だけ Qiita に記事を書いてたりした …</p><p>色々あって,技術的なことを書くブログを始めようと思いました (まる) .
今までは, Advent Calendar の時期だけ Qiita に記事を書いてたりしたんですが,
ちゃんとしてないやつも書いていこうかなってことで.</p>
<p>ちゃんとした系の記事は,出来るだけ外部に出していこうと思いますが,
調査不足だったり,よく分からない系とか徒然なるままな感じのことだったりとか,あと主に自分のためにしたこととかを書いていこっかなって感じです.</p>
<p>で,早速ですが一応ブログ立てたんで,立てる際した事とかを書いていく.</p>
<div class="section" id="auto-id-2">
<h2>サイトジェネレータの選定基準<a class="headerlink" href="#auto-id-2" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>まず,ブログに使うサイトジェネレータどうしよっかなあと悩んでいた.サイトジェネレータ一覧人気順は, <a class="reference external" href="https://www.staticgen.com/">https://www.staticgen.com/</a> から見れるっぽい.だいたい人気の上位陣は,</p>
<ul class="simple">
<li>Jekyll</li>
<li>Next</li>
<li>Hugo</li>
</ul>
<p>っぽい. Hugo は使ったことあって,割と使いやすくはあったんだけど,今回は見送った.理由は Markdown しか基本的に書けないから.
常々, Markdown は明示的に拡張記法を導入できないし,脚注とかが拡張だったりして機能的にたりない面があったりで,ちょっと辛いなあと思ってた.
なのでブログでは, Org-mode か reStructuredText を使いたいなと思ってた.</p>
<ul class="simple">
<li>Org-mode の場合 Emacs に HTML 出力させればいいので,大半のジェネレータでいける</li>
<li>reStructuredText は変換に Python の docutils を使うか, pandoc を使うといける</li>
</ul>
<p>で,色々探してた結果, Python 製の Pelican というジェネレータがあるらしく,標準で reStructuredText に対応してたしハイライトは Pygments を使って何とかできそうだったし,結構 Python を使うと色々ライブラリとの相性が良さそうだったので,今回はそれでいくことにしてみた.</p>
<p>テーマも良さそうなのがあったし,設定も結構簡単だったので,とりあえず満足してる.</p>
</div>
<div class="section" id="pelican">
<h2>Pelican の設定<a class="headerlink" href="#pelican" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p><a class="reference external" href="https://docs.getpelican.com/en/stable/quickstart.html">https://docs.getpelican.com/en/stable/quickstart.html</a> を見ながら,適当に自分の必要な感じでカスタマイズしてやった.</p>
<div class="section" id="pipenv">
<h3>Pipenv の設定<a class="headerlink" href="#pipenv" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>まずは, Pipenv を使って依存ライブラリを入れてく:</p>
<pre class="literal-block">
pip install pipenv
pipenv install pelican
</pre>
</div>
<div class="section" id="auto-id-3">
<h3>Pelican の設定<a class="headerlink" href="#auto-id-3" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<pre class="literal-block">
pipenv run pelican-quickstart
</pre>
<p>をやって,適当に質問に答えていく.今回は, GitHub Pages にデプロイする前提なのでそういう感じで答えていく.あと, Makefile の方が使いたかったのでそっちを使って,作られた <tt class="docutils literal">tasks.py</tt> は消しといた.ただ作られたやつそのままだとちょっと不便なので, <tt class="docutils literal">Makefile</tt> の以下の箇所は変えた.</p>
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span class="normal">1</span>
<span class="normal">2</span>
<span class="normal">3</span>
<span class="normal">4</span>
<span class="normal">5</span>
<span class="normal">6</span>
<span class="normal">7</span></pre></div></td><td class="code"><div><pre><span></span><span class="gd">- PELICAN?=pelican</span>
<span class="gd">- GHP_IMPORT?=ghp-import</span>
<span class="gi">+ PELICAN?=pipenv run pelican</span>
<span class="gi">+ GHP_IMPORT?=pipenv run ghp-import</span>
<span class="gd">- GITHUB_PAGES_BRANCH=master</span>
<span class="gi">+ GITHUB_PAGES_BRANCH=gh-pages</span>
</pre></div></td></tr></table></div>
<p>GitHub へのデプロイのためには, <tt class="docutils literal"><span class="pre">ghp-import</span></tt> というパッケージが必要っぽいのでそれも入れた:</p>
<pre class="literal-block">
pipenv install ghp-import
</pre>
<p>後は, <a class="reference external" href="https://docs.getpelican.com/en/stable/settings.html">https://docs.getpelican.com/en/stable/settings.html</a> を見ながら, <tt class="docutils literal">pelicanconf.py</tt> と <tt class="docutils literal">publishconf.py</tt> を適当にいじった.最終的な結果は,右上の GitHub ボタンからソースに飛べるので適当に見てください.</p>
<p>2つだけ言っておくと,</p>
<ul class="simple">
<li><tt class="docutils literal">pelicanconf.py</tt> の内容は選ぶテーマによってかなり書く内容が異なる.後, Pelican の本体とテーマでパラメータ名が異なったりする.なので,パラメータが効かなかった場合,テーマのテンプレートを読みにいかないといけない場合がある.</li>
<li><tt class="docutils literal">make html</tt> では <tt class="docutils literal">pelicanconf.py</tt> が, <tt class="docutils literal">make publish</tt> では <tt class="docutils literal">publishconf.py</tt> が参照されてビルドされる.この時, <tt class="docutils literal">MENUITEMS</tt> などに他ページへのリンクを書いたりすると,公開する URL によってはリンクの調整が必要になったりする.今回は <tt class="docutils literal">/blog/</tt> 以下に公開するので,リンクを <tt class="docutils literal">/somefile</tt> とか書くとずれる.見た感じ Pelican ではこの調整をしてくれないので,今回は <tt class="docutils literal">publishconf.py</tt> で調整を明示的にやるコードを書いた.</li>
</ul>
<p>後ディレクトリ構成は,基本的に <tt class="docutils literal">content</tt> の下に</p>
<ul class="simple">
<li><tt class="docutils literal">articles</tt>: 記事を書いて置く.</li>
<li><tt class="docutils literal">pages</tt>: 記事でない静的文書コンテンツを置く.</li>
<li><tt class="docutils literal">asset</tt>: 文書でない静的ファイルを置く.</li>
</ul>
<p>みたいな構成にした (<tt class="docutils literal">asset</tt> 以外は標準の配置) .後 <tt class="docutils literal">asset</tt> は <tt class="docutils literal">STATIC_PATHS</tt> に指定して Pelican にコピーしてもらう必要があるので,それもやった.</p>
</div>
<div class="section" id="auto-id-4">
<h3>テーマの選別<a class="headerlink" href="#auto-id-4" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>だいぶ見にくいけど, <a class="reference external" href="http://www.pelicanthemes.com/">http://www.pelicanthemes.com/</a> からテーマが色々見れるっぽい.とりあえず良さそうで開発も活発そうな <a class="reference external" href="https://github.com/alexandrevicenzi/Flex">Flex</a> を使うことにした.</p>
<p>Git submodule を使ってテーマをリポジトリに追加する:</p>
<pre class="literal-block">
git submodule add https://github.com/alexandrevicenzi/Flex.git themes/Flex
</pre>
<p>後は, <tt class="docutils literal">pelicanconf.py</tt> に以下を足せばいい:</p>
<pre class="literal-block">
THEME = './themes/Flex'
</pre>
<p><a class="reference external" href="https://github.com/alexandrevicenzi/Flex/tree/master/docs">https://github.com/alexandrevicenzi/Flex/tree/master/docs</a> を参考に <tt class="docutils literal">pelicanconf.py</tt> を色々修正.後,気になったデザインを修正して, <tt class="docutils literal">content/asset/custom.css</tt> に置いた.これを <tt class="docutils literal">CUSTOM_CSS</tt> パラメータに指定すると Flex テーマが読み込んでくれる.</p>
</div>
<div class="section" id="auto-id-5">
<h3>プラグインの設定<a class="headerlink" href="#auto-id-5" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>公式プラグインが全て1つのリポジトリで管理されてるっぽい.とりあえずそれを, Git submodule で追加:</p>
<pre class="literal-block">
git submodule add https://github.com/getpelican/pelican-plugins.git plugins
</pre>
<p>後は, <tt class="docutils literal">pelicanconf.py</tt> に以下を追加する:</p>
<pre class="literal-block">
PLUGIN_PATHS = ['plugins']
</pre>
<p>とりあえず,</p>
<ul class="simple">
<li><tt class="docutils literal">tipue_search</tt></li>
<li><tt class="docutils literal">related_posts</tt></li>
</ul>
<p>の2つを導入しといた.まあ,機を見て他にも導入したり導入やめたりするかも.</p>
</div>
<div class="section" id="auto-id-6">
<h3>プライバシーポリシーとか諸々の設置<a class="headerlink" href="#auto-id-6" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>左にある諸々を書いた. <tt class="docutils literal">pages</tt> 以下に置くと自動で認識して表示される.順番を制御したかったので, <tt class="docutils literal">pelicanconf.py</tt> に以下の記述を足した:</p>
<pre class="literal-block">
PAGES_SORT_ATTRIBUTE = 'source_path'
</pre>
<p>このパラメータは Flex テーマで処理される.標準で <tt class="docutils literal">PAGE_ORDER_BY</tt> というパラメータもあるんだけど,現状未対応っぽい <a class="footnote-reference" href="#support-page-order-in-flex-theme" id="auto-id-7">[4]</a>.後はページを表示したい順に,ファイル名に接頭辞で番号をつければ良い.</p>
<p>Google Analytics とかの導入を見据えて,いくつかのサイトを参考にしながらプライバシーポリシーを設置した.参考にしたのは以下のサイト:</p>
<dl class="docutils">
<dt>Quora のプライバシー規定</dt>
<dd><p class="first">かなりの部分参考にしたって感じ.
デザインは結構終わってるけど,かなり詳細に書いてあって好感が持てる内容だった.</p>
<p class="last"><a class="reference external" href="https://jp.quora.com/about/privacy">https://jp.quora.com/about/privacy</a></p>
</dd>
<dt>Google のプライバシーポリシー</dt>
<dd><p class="first">2番目に参考にした.
こちらも内容が丁寧で好感が持てる.
ただ, Quora とのユーザ層の違いと多分法務部がかなりちゃんとチェックしてるんだろうけど,
ところどころぼかしてあったり,エンジニアの対外的な態度と違う内容 (危険性を説明すべきところを,まるで問題ないように説明している)
が書いてあったりする.そこら辺は,さすが大企業だなって感じだった (こなみ) .</p>
<p class="last"><a class="reference external" href="https://policies.google.com/privacy?hl=ja">https://policies.google.com/privacy?hl=ja</a></p>
</dd>
<dt>Qiita のプライバシーポリシー</dt>
<dd><p class="first">一応参考にした.
ただ,どっちかというと他の2つより規定みたいな感じだった.
よく言えばちゃんとしている,悪く言えば説明する気がないみたいな感じ.
正直どこら辺参照したかすら覚えてない.</p>
<p class="last"><a class="reference external" href="https://qiita.com/privacy">https://qiita.com/privacy</a></p>
</dd>
</dl>
<p>Google Analytics 的には, Cookie の使用と Google Analytics の使用が明示されていれば良いっぽい <a class="footnote-reference" href="#google-analytics-privacy-rule" id="auto-id-8">[3]</a>. 後は,免責事項とか適当に足したサイトの説明とかも足した.</p>
</div>
</div>
<div class="section" id="github-pages">
<h2>GitHub Pages の設定<a class="headerlink" href="#github-pages" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<div class="section" id="auto-id-9">
<h3>GitHub Pages の有効化<a class="headerlink" href="#auto-id-9" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>リポジトリの Settings から <tt class="docutils literal"><span class="pre">gh-pages</span></tt> ブランチの内容を GitHub Pages で表示させるようにした.</p>
<p>後,パーソナルサイトは今の所作る予定がないので, <a class="reference external" href="https://mizunashi-mana.github.io/">https://mizunashi-mana.github.io/</a> は <a class="reference external" href="https://mizunashi-mana.github.io/blog/">https://mizunashi-mana.github.io/blog/</a> にリダイレクトされるようにした.内容は <a class="reference external" href="https://github.com/mizunashi-mana/mizunashi-mana.github.io/blob/ed6aebc132267360a7ccd95717d7b5fe64ec7fa2/index.html">https://github.com/mizunashi-mana/mizunashi-mana.github.io/blob/ed6aebc132267360a7ccd95717d7b5fe64ec7fa2/index.html</a> にあるけど,単純に <tt class="docutils literal">refresh</tt> でリダイレクト指定して,それでだめなら JavaScript にフォールバックする感じ.</p>
<p>これで, <tt class="docutils literal">make github</tt> すると GitHub Pages にデプロイされるようになる.</p>
</div>
<div class="section" id="circle-ci">
<h3>Circle CI による自動デプロイ環境<a class="headerlink" href="#circle-ci" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h3>
<p>事故を防ぐため, PR で記事を追加していくことにした. <tt class="docutils literal">master</tt> はプロテクトして基本プッシュせず, PR がマージされた時に Circle CI を回すようにした.</p>
<p>Circle CI は <a class="reference external" href="https://circleci.com/docs/2.0/language-python/">https://circleci.com/docs/2.0/language-python/</a> を参考に Python のバージョンを 3.7 にして,色々書くみたいなことやった.最終的な内容は, <a class="reference external" href="https://github.com/mizunashi-mana/blog/blob/master/.circleci/config.yml">https://github.com/mizunashi-mana/blog/blob/master/.circleci/config.yml</a> から見れるので気になったらどうぞ.</p>
<p>後, <tt class="docutils literal"><span class="pre">gh-pages</span></tt> の方はビルドを止めるため,何のタスクもない設定ファイルを追加した:</p>
<pre class="literal-block">
version: 2
jobs: {}
workflows:
version: 2
</pre>
<p>後は, <tt class="docutils literal">GITHUB_TOKEN</tt> 環境変数を既に Circle CI 使ってるプロジェクトから import してくればおk.一から作る場合は, <a class="reference external" href="https://github.com/settings/tokens">https://github.com/settings/tokens</a> から適当に発行すれば良さそう.</p>
</div>
</div>
<div class="section" id="auto-id-10">
<h2>他にやりたいこと<a class="headerlink" href="#auto-id-10" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>現状幾つか解決したい問題と追加したい機能もあって,</p>
<ul class="simple">
<li>VSCode の reStructuredText プラグインのアンダーライン補完が日本語だとうまく動かないので,これを修正したい.</li>
<li>全文検索に対応したい.</li>
<li>各メニューを日本語対応させたい.</li>
<li>シェアボタンを追加したい.</li>
<li>Google Analytics を追加したい.</li>
</ul>
<p>ぐらいはやりたい.</p>
<p>VSCode の件は,プラグインは日本語文字の width を 1 とカウントしているのに対し,
docutils の方は East-Asian Width を考慮して換算してるっぽくて <a class="footnote-reference" href="#docutils-column-width" id="auto-id-11">[1]</a> ,
結果補完されるアンダーラインが短い判定を受けてしまうという感じ.
これぐらいならすぐ直せそうなので,近いうちに PR を送ると思う.</p>
<p>全文検索は, Tipue Search 用の JSON を吐き出してくれるプラグインが既にあるっぽくて <a class="footnote-reference" href="#pelican-tipue-search-plugin" id="auto-id-12">[2]</a> ,
後はテーマが対応していれば問題ないみたい.
しかも,使ってるテーマのイシューに検索対応したいみたいなことが <a class="reference external" href="https://github.com/alexandrevicenzi/Flex/issues/49">書いてある</a> .
なのでこちらも近いうちに, PR 送ってみようかなと.</p>
<p>後メニュー日本語対応は, <a class="reference external" href="https://github.com/alexandrevicenzi/Flex/blob/v2.2.0/translations/en/LC_MESSAGES/messages.po">https://github.com/alexandrevicenzi/Flex/blob/v2.2.0/translations/en/LC_MESSAGES/messages.po</a> の翻訳版を投げれば良さそうなので,これも近いうちにやる.アーカイブページの日付表示も変えられるようにしたい.これも近いうちにやる.</p>
<p>シェアボタンを表示する仕組みはテーマにはなさそう. Disqus を追加するとついでに付いてくるやつで凌ごうか悩み中.</p>
<p>Google Analytics はアカウント設定がちょっと億劫でやってないけど,そのうちやる.</p>
<p>(やるとは言っていない)</p>
</div>
<div class="section" id="auto-id-14">
<h2>あまり乗り気じゃないもの<a class="headerlink" href="#auto-id-14" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>以下は一応考えてはいるけど,現状あんまり乗り気じゃないもの.</p>
<ul class="simple">
<li>広告表示</li>
<li>コメント機能</li>
<li>CSS Rhythmic Sizing</li>
<li>GDPR (ePrivacy) 対応</li>
</ul>
<p>大体テーマで対応してるので,それほど追加は手間ではないんだけど,とりあえず様子見.</p>
<p>広告表示は,収益出るようだったら Google Adsense とか設置したいけど,今はいいかな.</p>
<p>コメント機能も Disqus を登録すればいいんだけど, Disqus 利用者そんなにいなさそうだしはてなブックマークとかで良さそう.</p>
<p>CSSについては,今は適当に <tt class="docutils literal"><span class="pre">line-height:</span> 2.0;</tt> とかしてるんだけど, Vertical Rhythm を導入したい気持ちがある.ただ確か現状 CSS 標準ではなかったはずなので,ちょっと見送ってる (あんまり調べてない) .気が変わるか安定したら対応するかもしれない.</p>
<p>GDPR (ePrivacy) 対応は現状は特に Cookie を使用していないので問題ないはず.今後 Google Analytics や Google Adsense を導入する場合どうなるかの話だけど,正直どういう対応をすればいいか分からないので保留中.まあ, Cookie の制限については, ポップアップで Cookie の同意をとってから Google Analytics のコードとかを起動すればいいだけだし,その他については Google Analytics は修正条項が適用されたモードで起動すれば大丈夫っぽい.ただそもそも日本語で書かれたマイナーコンテンツを EU 圏がそこまで見るかって話だし,熱心に対応する予定はない.</p>
</div>
<div class="section" id="auto-id-15">
<h2>まとめ<a class="headerlink" href="#auto-id-15" title="Permalink to this headline"><i class="fas fa-link anchor-link"></i></a></h2>
<p>雑に続けていければなと思うので,よろしくお願いします.</p>
<table class="docutils footnote" frame="void" id="docutils-column-width" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-11">[1]</a></td><td><a class="reference external" href="https://github.com/docutils-mirror/docutils/blob/e88c5fb08d5cdfa8b4ac1020dd6f7177778d5990/docutils/utils/__init__.py#L628to">https://github.com/docutils-mirror/docutils/blob/e88c5fb08d5cdfa8b4ac1020dd6f7177778d5990/docutils/utils/__init__.py#L628to</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="pelican-tipue-search-plugin" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-12">[2]</a></td><td><a class="reference external" href="https://github.com/getpelican/pelican-plugins/tree/master/tipue_search">https://github.com/getpelican/pelican-plugins/tree/master/tipue_search</a></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="google-analytics-privacy-rule" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-8">[3]</a></td><td>Google Analytics の <a class="reference external" href="https://www.google.com/intl/ja/analytics/terms/jp.html">利用規約</a> 7. プライバシー に記載あり.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="support-page-order-in-flex-theme" rules="none">
<colgroup><col class="label"/><col/></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#auto-id-7">[4]</a></td><td><a class="reference external" href="https://github.com/alexandrevicenzi/Flex/issues/170">https://github.com/alexandrevicenzi/Flex/issues/170</a></td></tr>
</tbody>
</table>
</div>
<script>
var contentMetadataForCustomJS = {
'type': 'articles',
'title': document.title,
'url': location.protocol + '//' + location.host + location.pathname,
'source_path': 'articles/2019/03/start-blog.rst',
'github_url': 'https://github.com/mizunashi-mana/blog/blob/master/content/articles/2019/03/start-blog.rst'
}
</script><script async src="https://mizunashi-mana.github.io/blog/dist-asset/bundle.js"></script>