前の投稿では、発言に関数を追加しました。
この投稿では、積型を追加します。本格的なプログラミング言語では、積は struct、record、tuple などでも呼ばれています。
型を複数取り、一個の型に重ねることができるのは積です。例えば、関数から複数の値を戻したければ、積は使えます。
型を二つ重ねる積型は「ペア」といって、τ1×τ2で表記します。⟨e1,e2⟩はペア定数の式です。
ペアを使い他のペアを合わせることによって、二個の型以上の積を作り上げられます。
ペアを使用する為、中身の値を抽出せねば。その為e⋅Lとe⋅Rの射影式も追加します。eはペアであれば、この式は左と右の値をペアから射影します。
次、他の型を一切含まぬ積型を紹介します。この型を「単位」(unit)と呼び、1で表記します。値が一つだけあるので、その値も「単位」と呼び、⟨⟩で表記します。
値が一つしかないから、単位型はあまり役立たないと思われるかもしれません。しかし、関数から何も戻したくなかったら役立てます。
例えば、多くのプログラミング言語では、関数は副作用を実行できます。副作用というのは、値を戻す以外のこと、例えばファイルを変更したりインターネットに繋がったりすることを言います。
実は、或る関数は副作用の為だけに使われ、面白い値を戻す必要などありません。この場合、単位を戻すのが便利です。
違う言語は単位を他の名前で表します:
- C, C++, Java には
void
- Python には
None
- JavaScript には
undefined
- Ruby には
nil
τ::= ∣ ∣ e::= ∣ ∣ ∣ ∣ …1τ1×τ2…⟨⟩⟨e1,e2⟩e⋅Le⋅R
単位の値の型は単位です。
Γ⊢⟨⟩:1式が二つあって、それぞれには型があれば、ペアを作り出せます。
Γ⊢⟨e1,e2⟩:τ1×τ2Γ⊢e1:τ1Γ⊢e2:τ2左側か右側を射影できます。
Γ⊢e⋅L:τ1Γ⊢e:τ1×τ2Γ⊢e⋅R:τ2Γ⊢e:τ1×τ2
単位は値。
⟨⟩ val中の式が両方値である場合、ペアも値。
⟨e1,e2⟩ vale1 vale2 val左側の式が踏み出せれば、ペアもできます。
⟨e1,e2⟩↦⟨e1′,e2⟩e1↦e1′左側は値ですけれど、右側は踏み出せれば、ペアもできます。
⟨e1,e2⟩↦⟨e1,e2′⟩e1 vale2↦e2′射影式は、まずペアを値にします。次、値である時にはペア定数になっていますから、それの左側か右側の式に踏み出します。
e⋅L↦e′⋅Le↦e′⟨e1,e2⟩⋅L↦e1⟨e1,e2⟩ vale⋅R↦e′⋅Re↦e′⟨e1,e2⟩⋅R↦e2⟨e1,e2⟩ val
助手判断も機械的に更改します。
[x↦e]⟨⟩=⟨⟩[x↦e]⟨e1,e2⟩=⟨e1′,e2′⟩[x↦e]e1=e1′[x↦e]e2=e2′[x↦e]e1⋅L=e1′⋅L[x↦e]e1=e1′[x↦e]e1⋅R=e1′⋅R[x↦e]e1=e1′
fv(⟨⟩)=∅fv(⟨e1,e2⟩)=s1∪s2fv(e1)=s1fv(e2)=s2fv(e⋅L)=sfv(e)=sfv(e⋅R)=sfv(e)=s
結論する前、「積」の語源を考えましょう。
積型は何ゆえそう呼ばれているかと聞くと、型の値の数が原因です。積型にある型の値の数をかければ、積型の値の数になります。
例えばBoolには値が二つあります。trueとfalse。
ではBool×Boolという型には値がいくつありますか。それは 2×2=4。
- ⟨true,true⟩
- ⟨true,false⟩
- ⟨false,true⟩
- ⟨false,false⟩
Bool×1も見ましょう。値の数は2×1=2。
- ⟨true,⟨⟩⟩
- ⟨false,⟨⟩⟩
ですから単位の型を1で書くのは妥当です。単位の型である1は、積型の×の単位元です。
整数なら、任意の整数aを取れば、
a×1=aここでは×は掛け算。
同様に、∣τ∣というのを「τの値の数」という意味を付け、任意な型τを取れば、
∣τ×1∣=∣τ∣ここでは×は積型。
もっと全般的に言えば、
∣τ1×τ2∣=∣τ1∣×∣τ2∣ここで左側の×は積型で、右は掛け算を表します。
定理の証明もまたGitHubにあります。
次の投稿では和型を追加します。