教会のエンコーディング

数学においてチャーチ符号化はラムダ計算においてさまざまなデータ型を表現する方法です

型なしラムダ計算では、プリミティブなデータ型はラムダ抽象化用語で表される関数のみです。他の表記法では通常プリミティブ型とみなされる型(整数、ブール値、ペア、リスト、タグ付き共用体など)は、ネイティブには存在しません。

したがって、これらのさまざまなタイプのデータをラムダ項、つまり関数を引数として受け取り、関数を結果として返す 関数によって表現する方法が必要になります。

チャーチ数列は、ラムダ記法を用いた自然数の表現です。この手法は、ラムダ計算で初めてこの方法でデータを符号化したアロンゾ・チャーチにちなんで名付けられました。同様の考え方で他のデータ型を表現するように拡張することも可能です。

この記事では、ラムダ抽象化用語の代替構文をときどき使用します。λ xyz . Nは λ xyz . Nと省略され、必要に応じて2 つの標準コンビネータと も使用されます

使用

チャーチ符号化をそのまま実装すると、 から へのアクセス操作が遅くなります。ここで、 はデータ構造のサイズであるため、チャーチ符号化は実用的ではありません。[1]研究では、この問題は対象を絞った最適化で対処できることが示されていますが、ほとんどの関数型プログラミング言語では、中間表現を拡張して代数データ型を含めています[2]ただし、チャーチ符号化は部分評価や定理証明の自然な表現であるため、理論的な議論ではよく使用されます。[1]演算は、より高位の型を使用して型付けすることができ[3]プリミティブ再帰に簡単にアクセスできます。[1]関数が唯一のプリミティブデータ型であるという仮定により、多くの証明が合理化されます。

チャーチ符号化は完全ですが、表現上のみです。表現を一般的なデータ型に変換し、人々に表示するには、追加の関数が必要です。チャーチの定理による同値性の決定不能性のため、一般に2つの関数が外延的に等しいかどうかを判断することはできません。変換では、関数を何らかの方法で適用してそれが表す値を取得するか、その値をリテラルなラムダ項として参照します。ラムダ計算は通常、内包的等価性を使用するものとして解釈されます。内包的等価性と外延的等価性の定義が異なるため、結果の解釈に潜在的な問題が生じる可能性があります

教会のブール値

チャーチ・ブール値は、ブール値truefalse のチャーチ符号化です。一部のプログラミング言語では、これをブール演算の実装モデルとして利用しています。例としては、SmalltalkPico などがあります。

ブール論理は選択肢として考えられます。チャーチの真偽の符号化は 2つのパラメータの関数です。

  • true は最初のパラメータを選択します。
  • false は2 番目のパラメータを選択します。

次の 2 つの定義は Church ブール値として知られています。

この定義により、述語(つまり論理値を返す関数)を直接if節として機能させることができます。ブール値を返す関数を2つのパラメータに適用すると、最初のパラメータまたは2番目のパラメータのいずれかが返されます。

述語 x がtrueと評価された場合はthen 節に評価され述語 x がfalseと評価された場合はelse 節に評価されます。

truefalse は第1または第2のパラメータを選択するため、これらを組み合わせて論理演算子を使用することができます。notには複数の実装方法があることに注意してください。

例:

教会のペア

チャーチペアは、ペア(2要素組)型のチャーチ符号化です。ペアは関数を引数として受け取る関数として表現されます。引数が与えられると、その引数をペアの2つの要素に適用します。ラムダ計算における定義は、以下の通りです。

例えば、

教会の数字

チャーチ数とは、チャーチ符号化による自然数の表現である自然数nを表す高階関数は、任意の関数をそのn倍の合成に写像する関数である。簡単に言えば、数値は、任意の開始値から始めて、任意の関数をその回数だけ順番に適用することで、その数を表す。

チャーチ符号化は自然数の単項符号化であり、 [4]単純な数え上げに対応する。各チャーチ数は、構成によってこれを実現する。

すべてのチャーチ数列は2つのパラメータを取る関数です。チャーチ数列012 、… はラムダ計算において以下のように定義されます

0 関数をまったく適用しない ことから始めて、 1 関数を 1 回適用し、2関数を 2 回連続で適用し、 3 関数を 3 回連続で適用する、というように進めます。

チャーチ数字3は、任意の関数をある値から順に3回適用する連鎖です。指定された関数はまず指定された引数に適用され、次に関数自身の結果に順次適用されます。最終結果は数値 3 ではありません(指定された引数がたまたま 0 で、関数が後続関数である場合を除く)。チャーチ数字3は、関数自体であり、最終結果ではありません。チャーチ数字3 は、単に何かを3回行うことを意味します。これは「3回」が何を意味するかを示唆するものです

教会数字を使った計算

数値に対する算術演算は、結果として数値を生成します。チャーチ符号化では、これらの演算はラムダ抽象化によって表現され、オペランドを表すチャーチ数値に適用すると、結果を表すチャーチ数値にベータ還元されます。

加算のチャーチ表現では、次の恒等式が使用されます

後続演算 は、式 " " をβ 縮小することによって得られます

乗算 では、次の恒等式が使用されます

したがってn倍の合成を表現するチャーチ符号化のおかげで、べき乗演算は次のように与えられる。

先行操作は少し複雑です。繰り返した際に、与えられた関数 の適用が行われるような操作を考案する必要があります。これは、恒等関数 を1回だけ使用し、その後 に戻すことで実現できます

前述の通り、は恒等関数です。詳細な説明は以下を参照してください。これは、例えば二分の一化や階乗を同様の方法で実装することを示唆しています。

たとえば、ベータ還元すると になりベータ還元すると になりベータ還元すると になります

減算は、前の演算を指定された回数繰り返して適用することで表現されます。同様に、加算は、後続の演算を指定された回数繰り返して適用することで表現されます。

はn番目のテトレーション演算であり、 を表します

直接引き算と割り算

繰り返し演算としての加算が直接的なスタイルで表現されるのと同様に、減算も直接的かつより効率的に表現できます。

たとえば、は と同等になります

これにより、別の前身バージョンである beta-reducing も得られます 。

除算の直接的な定義は次のようにほぼ同様に与えられる。

このアプリケーションは、その後のステップを繰り返し発行するアクションのサイクルを作成しながら減算を実現します

上記の 3 つの定義のそれぞれにおいての代わりにを使用することもできます。

教会数字の機能表

関数代数身元関数定義ラムダ式
後継...
追加
乗算
累乗
前任者[a]

減算[a] ( Monus )...

注記:

  1. ^ ab 教会のエンコーディングでは、

先行関数

先行関数は次のように与えられる。

このエンコードは本質的にはアイデンティティを使用する

または

predの説明

ここでの考え方は以下のとおりです。チャーチ数に認識されるのは自体だけです。2つの引数とが与えられた場合通常通り、チャーチ数にできることは、その数を2つの引数に適用することだけです。この適用は、 n個の長いチェーンのうち、チェーンの1つ(具体的には左端)が恒等関数に置き換えられるように何らかの修正を加えることで実現されます。

ここでは変更されたであり、は変更された です自体は変更できないため、その動作は追加の引数 を通じてのみ変更できます

必要に応じて定義を変更しながら、 その追加の引数を外部から内部に渡すことで、目的が達成されます。

これはまさに定義のラムダ式に含まれているものです。

今ではそれが簡単にわかります

すなわち、イータ縮約と帰納法によって、

等々。

ペアによる予測の定義

上記の恒等式は、明示的にペアを用いてコード化することができます。例えば、いくつかの方法があります。

の展開は次のようになります。

これはより単純な定義ですが、より複雑なラムダ式につながります。

ラムダ計算におけるペアは、ここでのように内側から外側へ渡す場合でも、元の定義のように外側から内側へ渡す場合でも、本質的には単なる追加の引数です。別のエンコーディングは、先行する恒等式の2番目の変種に直接従います。

この方法は、元の「外から内へ」の定義にかなり近いものとなっており、同様にsの連鎖を生み出しますが、より無駄が多くなっています。しかし、以前の定義よりもはるかに無駄が少なくなっています。実際、その実行過程を辿ると、より合理化されながらも完全に同等の新しい定義に辿り着きます。

これにより、これは単に引数の修正とパスだけに関するものであることが完全に明らかになります。その縮約は次のように進行します。

何が起こっているかを明確に示しています。それでも、元の定義の方がはるかに優れています。トップダウン方式で動作するため、ユーザー定義関数が短絡した場合にすぐに停止できるからです。トップダウン方式は、次のような他の定義でも使用されます。

一般再帰による除算

自然数の除算は次のように実装できる。[5]

を計算するには、多くのベータ減算が必要になります。手動で減算を行わない限り、これはそれほど問題にはなりませんが、この計算を2回行う必要がない方が望ましいです(直接減算の定義を使用する場合を除く。上記参照)。数値を判定する最も単純な述語はIsZeroなので、その条件を検討してください。

しかし、この条件は と等価であり、 ではありません。この表現を用いると、上記の除算の数学的定義はチャーチ数上の関数として次のように変換されます。

期待どおり、この定義には の呼び出しが 1 つ含まれています。しかし、結果としてこの式は の値を返します

この問題は、divideを呼び出す前にnに1を加算することで修正できます。divideの定義は以下のようになります。

divide1は再帰的な定義です。Yコンビネータを使用して再帰を実装できます。div by; という新しい関数を作成してください

  • 左側
  • 右側には

取得するため、

それから、

どこ、

与える、

またはテキストとして、λの代わりに\を使用する。

除算 = (\n.((\f.(\xx x) (\xf (xx))) (\c.\n.\m.\f.\x.(\d.(\nn (\x.(\a.\bb)) (\a.\ba)) d ((\f.\xx) fx) (f (cdmfx))) ((\m.\nn (\n.\f.\xn (\g.\hh) (gf)) (\ux) (\uu)) m) nm))) ((\n.\f.\x. f (nfx)) n))

例えば、9/3は

割り算 (\f.\xf (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (f (fx))))))))) (\f.\xf (f (fx)))

ラムダ計算計算機を使用すると、上記の式は通常の順序で 3 に簡約されます。

\f.\xf (f (f (x)))

符号付き数字

チャーチ数字を符号付き数値に拡張する簡単な方法の一つは、正と負の値を表すチャーチ数字を含むチャーチペアを使用することです。[6] 整数値は2つのチャーチ数字の差です。

自然数は次のように符号付き数に変換される。

否定は値を交換することによって実行されます。

整数値は、ペアの一方がゼロであればより自然に表現されます。OneZero関数この条件を実現します。

再帰はYコンビネータを使って実装できる。

プラスとマイナス

加算は数学的には次のように定義されます。

最後の式はラムダ計算では次のように翻訳される。

同様に減算も定義される。

与えること、

掛け算と割り算

掛け算は次のように定義される。

最後の式はラムダ計算では次のように翻訳される。

除算についても同様の定義が示されていますが、この定義では、各ペアの一方の値は必ずゼロでなければなりません(上記のOneZeroを参照)。divZ関数を使用すると、ゼロの要素を持つ値を無視できます。

次に、 divZが次の式で使用されます。これは乗算の場合と同じですが、multがdivZに置き換えられます

有理数と実数

有理数と計算可能な実数もラムダ計算で符号化できます。有理数は符号付き数のペアとして符号化できます。計算可能な実数は、実数値との差が一定数だけ小さいことを保証する極限処理によって符号化できます。この極限値は必要に応じて小さくすることができます。[7] [8] 参考文献に記載されているソフトウェアは、理論的にはラムダ計算に翻訳可能です。実数が定義されれば、複素数は自然に実数のペアとして符号化されます。

上で説明したデータ型と関数は、あらゆるデータ型や計算をラムダ計算で符号化できることを示しています。これがチャーチ=チューリングのテーゼです。

他の表現による翻訳

現実世界の言語のほとんどは、マシンネイティブな整数をサポートしています。church関数unchurch関数は、非負整数とそれに対応するチャーチ数との間の変換を行います。これらの関数はHaskellで提供されています。ここで、は\ラムダ計算のλに相当します。他の言語での実装も同様です。

タイプChurch a = ( a -> a ) -> a -> a          church :: Integer -> Church Integer church 0 = \ f -> \ x -> x church n = \ f -> \ x -> f ( church ( n - 1 ) f x )                       unchurch :: Church整数->整数unchurch cn = cn ( + 1 ) 0           

述語

述語ブール値を返す関数です。最も基本的な述語は で引数がチャーチ数 の場合はを返し引数が他のチャーチ数 の場合は を返します。

次の述語は、最初の引数が 2 番目の引数以下かどうかをテストします。

アイデンティティのため、

等価性のテストは次のように実装できる。

リストエンコーディング

不変のリストはリストノードから構築されます。リストに対する基本的な操作は以下のとおりです。

関数説明
ゼロ空のリストを作成します。
イニルリストが空かどうかをテストします。
欠点指定された値を(空の可能性のある)リストの先頭に追加します。
リストの最初の要素を取得します。
しっぽリストの残りを取得します。

以下にリストの 4 つの異なる表現を示します。

  • リストノードごとに 2 つの Church ペア。
  • リストノードごとに 1 つの Church ペア。
  • 教会リスト –右折り表示。
  • スコットエンコーディング。

リストノードとしての2つのペア

空でないリストは Church ペアによって実装できます。

  • まず頭が入っています。
  • 2番目には尾が含まれています。

しかし、これは「null」ポインタが存在しないため、空のリストを表すものではありません。nullを表すには、このペアを別のペアでラップし、3つの値を与えます。

  • まず、ヌルポインター(空のリスト)。
  • Second.Firstにはヘッドが含まれます。
  • Second.Second には末尾が含まれます。

この考え方を用いると、基本的なリスト操作は次のように定義できる。[9]

表現説明
ペアの最初の要素はtrueなので、リストは null です。
null (または空のリスト) インジケーターを取得します。
null ではないリスト ノードを作成し、先頭にh、末尾にtを指定します。
2番目。1番目は頭です。
2番目。2番目は末尾です。

nilノードでは、 headtail が空でないリストにのみ適用される 場合、 second はアクセスされません。

リストノードとして1組

あるいは、[10]を定義する。

ここで、最後の定義はリストの安全な使用の一般的なパターンに従っており、 とリストの先頭と末尾を指します。

リストノードとしての1つのペアに対するその他の操作




教会リスト –右折り表現

チャーチペアを用いたエンコードの代替として、リストは右折り畳み関数を用いて識別することでエンコードできます。例えば、3つの要素x、y、zのリストは、コンビネータcと値nに適用するとcx(cy(czn))を返す高階関数でエンコードできます。これは、部分適用の関数的合成の連鎖(cx cy cz) nの適用と同等です。

このリスト表現はSystem Fの型で指定できます

チャーチ数列との明らかな対応は偶然ではありません。チャーチ数列は単項符号化と見なすことができ、自然数は単位値(つまり重要でない値)のリスト(例えば[() () ()])で表され、リストの長さが自然数の表現として機能します。このようなリストの右畳み込みは、要素の値を必然的に無視する関数を使用し、チャーチ数列で使用される連鎖関数合成、つまり(c () c () c ()) n = (f f f) nと同等です。

スコット符号化を使用してリストを表す

代替表現としてスコット符号化があり、継続の考え方を利用してより単純なコードを書くことができます。[11] (モーゲンセン・スコット符号化も参照)。

このアプローチでは、パターンマッチング式を用いてリストを観察できるという事実を利用します。例えば、Scala記法を用いると、空リストとコンストラクタを持つlist型の値を表す場合、リストを検査し、リストが空の場合と空でない場合の計算を行うことができます。ListNilCons(h, t)nilCodeconsCode(h, t)

リストマッチ{ case Nil => nilCode case Cons ( h , t ) => consCode ( h , t ) }           

は、およびlistに作用する方法によって決まります。したがって、リストを、そのようなおよびを引数として受け取る関数として定義すると、上記のパターンマッチの代わりに、次のように簡単に記述できます。nilCodeconsCodenilCodeconsCode

nに対応するパラメータをnilCodecに対応するパラメータをと表記しますconsCode。空のリストは nil 引数を返すものです。

h先頭と末尾を持つ空でないリストはt次のように与えられる。

より一般的には、代替引数を持つ代数的データ型は引数を持つ関数になります。thコンストラクタが引数を持つ場合、対応するエンコーディングの引数も引数を取ります。

スコット符号化は型なしラムダ計算で実行できますが、型と併用するには再帰と型多態性を備えた型システムが必要です。この表現において要素型Eを持つリストを型Cの値を計算するために使用すると、次のような再帰型定義になります。ここで、「=>」は関数型を表します。

type List = C => // nil 引数( E => List => C ) => // cons 引数C // パターンマッチングの結果               

任意の型を計算するために使用できるリストは、 を量化する型を持ちます。Cジェネリックなリスト[明確化が必要]も、型引数としてEを取ります。E

参照

参考文献

  1. ^ abc Trancón y Widemann, Baltasar; Parnas, David Lorge (2008). 「表形式表現と完全関数型プログラミング」. Olaf Chitil, Zoltán Horváth, Viktória Zsók (編). 関数型言語の実装と応用. 第19回国際ワークショップ, IFL 2007, ドイツ, フライブルク, 2007年9月27日~29日. 改訂版選定論文. コンピュータサイエンス講義ノート. 第5083巻. pp.  228~ 229. doi :10.1007/978-3-540-85373-2_13. ISBN 978-3-540-85372-5
  2. ^ Jansen, Jan Martin; Koopman, Pieter WM; Plasmeijer, Marinus J. (2006). 「データ型とパターンを関数に変換することによる効率的な解釈」. Nilsson, Henrik (編). Trends in functional programming. 第7巻. ブリストル: Intellect. pp.  73– 90. CiteSeerX 10.1.1.73.9841 . ISBN  978-1-84150-188-8
  3. ^ 「先行処理とリストは単純型ラムダ計算では表現できない」ラムダ計算とラムダ計算機okmij.org.
  4. ^ Jansen, Jan Martin (2013)、「λ計算によるプログラミング:チャーチからスコットへ、そしてその逆へ」、関数型コードの美しさ、コンピュータサイエンス講義ノート、第8106巻、Springer-Verlag、pp.  168– 180、doi :10.1007/978-3-642-40355-2_12、ISBN 978-3-642-40354-5
  5. ^ アリソン、ロイド、「ラムダ計算整数」。
  6. ^ Bauer, Andrej. 「ラムダ計算を用いた負数と複素数の表現」という質問に対するAndrejの回答。
  7. ^ “正確な実数演算”. Haskell . 2015年3月26日時点のオリジナルよりアーカイブ。
  8. ^ Bauer, Andrej (2022年9月26日). 「実数計算ソフトウェア」. GitHub .
  9. ^ ピアス、ベンジャミン・C. (2002).型とプログラミング言語. MITプレス. p. 500. ISBN 978-0-262-16209-8
  10. ^ Tromp, John (2007). 「14. 二項ラムダ計算と組合せ論理」. Calude, Cristian S (編).ランダム性と複雑性、ライプニッツからチャイティンまで. World Scientific. pp.  237– 262. ISBN 978-981-4474-39-9
    PDF: Tromp, John (2014年5月14日). 「二項ラムダ計算と組合せ論理」(PDF) . 2017年11月24日閲覧.
  11. ^ Jansen, Jan Martin (2013). 「λ-計算によるプログラミング:チャーチからスコットへ、そしてチャーチからスコットへ」. Achten, Peter、Koopman, Pieter WM (編). 『関数型コードの美しさ ― リーヌス・プラスマイヤー61歳の誕生日に捧げるエッセイ集』 . Lecture Notes in Computer Science. Vol. 8106. Springer. pp.  168– 180. doi :10.1007/978-3-642-40355-2_12. ISBN 978-3-642-40354-5
  • Stump, A. (2009). 「直接反射メタプログラミング」(PDF) . High-Order Symb Comput . 22 (2): 115– 144. CiteSeerX  10.1.1.489.5018 . doi :10.1007/s10990-007-9022-0. S2CID  16124152.
  • カートライト、ロバート. 「教会の数字とブール値の解説」(PDF) . Comp 311 — レビュー2.ライス大学.
  • ケンプ、コリン (2007). 「§2.4.1 チャーチ自然数、§2.4.2 チャーチブール値、第5章 TFPの導出技法」『実践的「完全関数型プログラミング」の理論的基礎』(PhD). クイーンズランド大学情報技術・電気工学部. pp.  14– 17, 93– 145. CiteSeerX  10.1.1.149.3505 . Churchやその他の類似のエンコーディングについて、その導出方法やその操作方法など、基本原理からすべてを説明します。
  • 教会数字のインタラクティブな例
  • ラムダ計算ライブチュートリアル:ブール代数
Retrieved from "https://en.wikipedia.org/w/index.php?title=Church_encoding&oldid=1320985439"