型システムを作ろうと試行錯誤してるのでメモ
0. そうだ、言語を作ろう
JavaScriptにトランスパイルできて、安全な操作と危険な操作が分離されてて、型が不整合を起こさないような言語を作りたいなあと思った。
ので、作る。
で、型システムを構築してたら色々考えることが多くて試行錯誤して多少まとまってきた部分があるので残しておこうと思う。
1. ジェネリクスのない型システム
最終的にジェネリクスは組み込むつもりだけど、とりあえずそこはおいといてジェネリクスのない型について考える。
JavaScriptへのトランスパイルを考えているので、TypeScriptと同じように number
とか string
とかそういうやつを扱うことにする。なお any
は入れない。もちろん 1
とか 'a'
などのリテラル型も扱う。
ジェネリクスを考えない場合、型は集合と同じようなものとして扱うことができる。そのため、以下は集合論の記号を使って型を表現する。
1-1. スーパータイプとサブタイプ
型
また、この時
TypeScriptの世界だとこれが成り立たないケースがあるのだが、少なくとも私の作る言語に関してはこれが成り立つように注意して実装する。
同様に、
-
真部分集合のようなノリでこう言っているが一般的にそう言うのかどうかは知らない。この文章のなかではそういうことにする。 ↩︎
1-2. 共用型と交差型
全ての
また、
が常に成り立つ。
また、
である。
以下が成り立つ(交換法則・結合法則・分配法則)。
1-3. トップ型とボトム型
これは存在しうる全ての型
このような型をトップ型と言い、
同様に、
これは存在しうる全ての型
このような型をボトム型と言い、
任意の値はトップ型の値である。
一方、ボトム型の値は全ての型の制約を満たすことになるが、そのような値は存在しない(number
でありかつ string
である型は存在しないことを考えれば分かるだろう)。そのため、ボトム型は値を持たない型である。
以下が成り立つ。
1-4. 否定型、差分型
任意の型
なお、型を一文字で表記する時に限り、
以下が成り立つ。
また、ド・モルガンの法則が成立する。
1-5. 型の広さ
1
のような型と number
のような型では、表すことができる範囲が異なる。
1
型の値は 1
しか存在しないが、 1
, 2
, 42
, 3.14
, ... など多くの値が number
型になる。
このとき、 1
型より number
型の方が広いと言うことができる。
以下が成立する。
と、これだけであれば、スーパータイプとサブタイプの関係性で済む話なので、わざわざ新たに広さという概念を持ち出したのは意味がある。
スーパータイプとサブタイプの関係性が成り立つのは一部の限定された型だけである。そのため、例えば string
と number
の広さを比較することはできない。
JavaScriptの number
は64bit浮動小数点数のため、表現できる値の種類は NaN
を厳密に区別しても 2^64 で、文字列より確実に少ないではないか、と思うかもしれないが、仮にリソースに制限がなかったとしたら有理数と文字列は1対1に対応させることが可能なのでどちらも可算無限という話になり、まあここらへんを突き詰めていくと極限順序数がどうの無限の濃度がどうのという話になるのだがここではそちらに踏み込む必要はないので置いておく。
ここでは、厳密な広さではなく広さレベルとでも言うべきものを導入して考える。number
と string
はどちらも広さレベル1をとし、
型
有限個の広さレベル0または1の型の共用型
を考える。
トップ型は存在しうる全ての型の共用型と捉えることが可能だが、有限個の広さレベル0または1の型で共用体を作ってもトップ型を表現することはできない。
一方、
以下が成立する。
1-6. 型同士の二項関係
既にスーパータイプとサブタイプの関係性に触れたが、それ以外を含めた型同士の関係を定式化できるように拡張したい。
一般に、型
の4つの型に分けて考えることができる。
上図においては全ての型が存在するように描いているが、実際は各型は
ただし、各型の共用型が
以下、
とする。また、
とすると、
以下、
とする。
以下、15通りを列挙するが長くなるので折りたたむ。
-
の場合。\mathrm{rel}(A, B) = (\mathrm{false}, \mathrm{false}, \mathrm{false}, \mathrm{true}) である。A = \bot \land B = \bot
-
の場合。\mathrm{rel}(A, B) = (\mathrm{false}, \mathrm{false}, \mathrm{true}, \mathrm{false}) である。A = \top \land B = \top
-
の場合。\mathrm{rel}(A, B) = (\mathrm{false}, \mathrm{false}, \mathrm{true}, \mathrm{true}) である。A = B
-
の場合。\mathrm{rel}(A, B) = (\mathrm{false}, \mathrm{true}, \mathrm{false}, \mathrm{false}) である。A = \bot \land B = \top
-
の場合。\mathrm{rel}(A, B) = (\mathrm{false}, \mathrm{true}, \mathrm{false}, \mathrm{true}) である。A = \bot
-
の場合。\mathrm{rel}(A, B) = (\mathrm{false}, \mathrm{true}, \mathrm{true}, \mathrm{false}) である。B = \top
-
の場合。\mathrm{rel}(A, B) = (\mathrm{false}, \mathrm{true}, \mathrm{true}, \mathrm{true}) である。A \sub B
-
の場合。\mathrm{rel}(A, B) = (\mathrm{true}, \mathrm{false}, \mathrm{false}, \mathrm{false}) である。A = \top \land B = \bot
-
の場合。\mathrm{rel}(A, B) = (\mathrm{true}, \mathrm{false}, \mathrm{false}, \mathrm{true}) である。B = \bot
-
の場合。\mathrm{rel}(A, B) = (\mathrm{true}, \mathrm{false}, \mathrm{true}, \mathrm{false}) である。A = \top
-
の場合。\mathrm{rel}(A, B) = (\mathrm{true}, \mathrm{false}, \mathrm{true}, \mathrm{true}) である。A \supset B
-
の場合。\mathrm{rel}(A, B) = (\mathrm{true}, \mathrm{true}, \mathrm{false}, \mathrm{false}) である。A = \bar B
-
の場合。\mathrm{rel}(A, B) = (\mathrm{true}, \mathrm{true}, \mathrm{false}, \mathrm{true}) である。A \cap B = \bot
-
の場合。\mathrm{rel}(A, B) = (\mathrm{true}, \mathrm{true}, \mathrm{true}, \mathrm{false}) である。A \cup B = \top
-
の場合。\mathrm{rel}(A, B) = (\mathrm{true}, \mathrm{true}, \mathrm{true}, \mathrm{true})
-
(
にはなりえないため(\mathrm{false}, \mathrm{false}, \mathrm{false}, \mathrm{false}) より1通り少ない) ↩︎2^4 = 16
1-7. 否定型の二項関係
明らかに、
である。また、
となる。すなわち、
1-8. スーパータイプ・サブタイプの関係から二項関係の構築
以下が成り立つ。
したがって、
ここで、
のとき、
であることから、
が成立する。
また、
のとき、
なので、
が成立する。
よって、
で求めることができる。