Caty-Jcentric 型理論/型推論/意味論
形式系の微妙なところ
http://d.hatena.ne.jp/m-hiyama-memo/20090828/1251438577 より(竹内本を参考)
意味じゃなくて、もっぱら記号の話。
- 定数とarity 0の関数
- 関数と演算子
- fooとfoo()の区別
- 関数の引数渡しのバリエーション:可変引数、省略とデフォルト値、名前付き引数
- 関数記号と関係記号の区別
- ソートを入れるか、特に真偽値のソート
- 真偽値のソートがあれば、関係記号も論理記号も関数記号じゃ
追記:
- 構文と意味の区別は実際にはエエカゲン、ちゃんとやる人は滅多にいない。
- ちゃんとやればめんどくさい、エエカゲンだと混乱する。いつものジレンマ!
- やるなら、オーバーバーよりは太いブラケットが便利。
- 意味に対するコード(1つに定まる標準の表現/名前)はゲーデル記法。
setoid with restriction predicate
- なんでsetoidか? 「1 と 1.0 問題」 -- なんでもsetoid
- setoid射 「1 と 1.0」のとき
- setoid射 バッグ配列のとき
- setoid射 dateを入れたとき -- 変わり続けるsetoid構造
- なんで with restriction predicate か? 「integer, number 問題」
- type integer = number(isInteger = true);
- enum [1, 2] ≡ number(enum = [1, 2]) 構文糖衣
- integer, enum, スキーマ属性はすべて restriction predicateの例。
原子論理式
論理式 | 意味 | 記号の乱用 |
---|---|---|
x is T | val[T](x)∈Val(T) | x ∈ T |
S included T | Val(S) ⊆ Val(T) | S ⊆ T |
S disjoint T | Val(S)∩Val(T) = 0 | S ◇ T |
「S ◇ T」は単なる略記で問題ないが、「x ∈ T」は相当にヤバイ。「S ⊆ T」も極めて不正確だが許して。
tag関数とtags関数
- まったくの別物
- 名前はtagだが、ほんとはタグとは限らない(暗黙タグも)
- tagはインスタンス領域の全域関数
- tagsは型表現に対して定義される(JSONインスタンスも型表現とみなせるが、でも)
- x is T ならば、 tag(x)∈tags(T)
tags(T) が非空有限集合である型表現はプロパー(特殊でない)。
接頭辞
接頭辞記法 α=>T は説明のためだけに使う。
- 予約語接頭辞:number, string, boolean, null, array, object, bag
- 使用不可能:integer, tuple, list, enum, multi, その他の予約語
- 特別扱い:any, never
- 予約語ではないすべてのタグ名は接頭辞
tags(T) = {α} のときに限り、 α=>T と書いてよい。
型推論の演繹系
いずれは実装する。
- 変数のない項(閉じた項)と変数のない論理式(文)だけを考える。
- 仮定のない、絶対的な証明だけを考える。
- 論理式は、原子論理式またはそれの連言に限る。
- ホントの組み込み基本型は、number, string, boolean, null の4つだけとする。
- 組み込み型と事前定義型(predefined type)は別。integerは事前定義型扱い。
- 特別な型として、never, undefined, anyを使う。意味論では必須。
- 関数形式型構成子は、array, object, bagの3つとする。
- 演算子形式型構成子は、?, &, @name, | とする。
- その他、制限述語。
変数のある項/論理式、仮定のある証明(この2者は相関している)もいずれは扱う。
外の圏と中の演算
http://d.hatena.ne.jp/m-hiyama-memo/20090828/1251436086 より:
JSON領域が含まれる外の圏に次の演算が入る。
- (X, p)|(Y, q) := (X + Y, [p, q]) ([q, q]は余デカルトペア)
- (X, p)*(Y, q) := (X×Y, p(*)q) (p(*)qは∧によるテンソル積)
- (X, p)&(Y, q) := (X∩Y, p∧q)
JSON領域内では:
- 制限された演算 |
- キーを適当に決めてobject構成
- 演算 &、ただし、結果的に X = Y となる。
曇ったスノーグローブ。
型推論のための定理
http://d.hatena.ne.jp/m-hiyama-memo/20090826/1251259922 より:
たいした内容ではないけど、名前を付けておこう。
- タグ排他性の原理:α≠β ⇒ (@α A)∩(@β B) = 0
- 単調性の原理:S ⊆T ⇒ tags(S)⊆tags(T)
- ハテナ定理:正規形の式なら、一番外側の'?'で確定型か不確定型か判断できる。
- ν(nu)定理:Tがプロパーなとき、ν(T) ≧ 1、ν(T) = n なら、Tはn成分のユニオンとして書ける。
- 排他的包含の原理:(α=>A) ⊆ (β1=>B1 | ... |βn=>Bn) ⇔ α = βi で (α=>A) ⊆ (βi=>Bi)
タグ排他性の原理は、もっともベーシックな事実。単調性の原理と排他的包含の原理は、そうなるように作りましょう、という指導原理。ν定理も指導原理に近い。が、ハテナ定理は定理だ。
型表現のハテナ正規化
http://d.hatena.ne.jp/m-hiyama-memo/20090826/1251259924 より:
- A?? → A?
- (A?|B) → (A|B)? など
- A? & B → A & B など
- A? & B? → (A & B)?
- bag [A?] → bag [A] (ハテナ定理には不要)
- @name A? → @name A (ハテナ定理には不要)
ハテナ定理に必要なのは、演算子?, |, & に関する正規化だけ。
項の計算
- ハテナ正規化は計算
- 分配法則による展開は計算
- & を下に押し込めて消してしまう計算
& の計算
- array [Ai] & array [Bi] ⇒ array [Ai & Bi]
- object {pi: Ai} & object {pi:Bi} ⇒ object {pi: Ai & Bi}
- (bag [A]) & (bag [B]) ⇒ bag [A & B]
- (@α A) & (@α B) ⇒ @α (A & B)
neverの計算
- array [... never ...] ⇒ never
- object {... never ...} ⇒ never
- bug [never] ⇒ never
- @α never ⇒ never
- never & X ⇒ never
- never | X = X
anyの計算
- any & X ⇒ X
- any | X 制約違反
分解還元法による演繹系
http://d.hatena.ne.jp/m-hiyama-memo/20090827/1251338342 より:
Catyの型推論のために、分解還元法というのを考えた。シーケント計算とタブローの中間のような感じのもの。推論は逆向きに(結論から仮定へと)行われるので、次の用語を導入する。
- 分解図 -- 推論図(1ステップ)の逆
- 還元図 -- 証明図(nステップ)の逆
シーケントに対応するのは、有限個(n≧0)の原子論理式をカンマで区切った列。列式、または単に式と呼ぶ。列式のなかの原子論理式は次のいずれか:
- 真であるとすぐに判断できる。
- 偽であるとすぐに判断できる。
- 分解できる。
「真であるとすぐに判断できる」原子論理式は、aを基本型記号(basic type symbol)だとして、a⊆a か a⊆any のどちらかの形。あきらかに偽の論理式は色々ある。
分解とは、列式のなかの1個の原子論理式に注目して、それを1個以上の別な原子論理式の集合(構文的にはカンマ区切り列)に置き換えること。分解が p→q1, ..., qk のとき、次の性質が成立している。
- |= p ⇔ |= (q1∧...∧qk)
- rank(p) > rank({q1, ..., qk})
上の主張が確認できるためには、原子論理式に対する意味論が定義されていることと、rankが定義されていることが必要。
意味論は意味領域がないとしょうがないが、rank関数は構文的に定義される。
- 基本型記号のrankは0
- 型項(型表現)のrankは、含まれる型関数記号、型演算子記号の総数。
- 原子論理式のrankは、左右のrankの和
- 列式のrankは、原子論理式rankの最大値
分解図では、上の式と下の式が意味論的には等価で、下の式のほうが確実にランクが下がっていることになる。常に分解可能性が保証できれば、ランクはゼロに落ちるから、列式の決定可能性が(メタ)証明できる。
意味論を適切に構成すれば、完全性(complete = sound and adequate)が成立する。完全になるように意味論を組み立てる、ってのがホントウのところだけど。
以上の話は、述語pに対する λx:A.p というラムダ式の定義域Aの議論。領域計算と呼びたいが、領域が多用されているから、台領域(キャリア;carrier)計算とでもするか。台の計算をもとにして、その上のラムダ式の計算が可能となる。ラムダ式の計算のほうが制限(restriction)計算となる。制限の実体はスキーマ属性だから属性計算と呼んでもいいかもしれない。
分解還元法の分解図
http://d.hatena.ne.jp/m-hiyama-memo/20090827/1251349683 より:
u = undefined として、記号の乱用で u = {u}。ブラケット内の数値はランクが減少する量。
●opt-rightA ⊆ B+u
[u!∈A] -----------[-1]
A ⊆ B●opt-both
A+u ⊆ B+u
[u!∈A, u!∈B] -----------[-2]
A ⊆ B●object
object {pi: Ai} ⊆ object {pi: Bi}
------------------------------------[-2]
Ai ⊆ Bi (i=1, ..., n)●array
array [Ai] ⊆ array [Bi]
------------------------------------[-2]
Ai ⊆ Bi (i=1, ..., n)●union-left
A|B ⊆ C
----------------[-1]
A ⊆ C, B ⊆ C●union-right
α=>A ⊆ (α=>B | C)
----------------------[-1]
A ⊆ B●bag
bag [A] ⊆ bag [B]
--------------------[-2]
A ⊆ B@α A ⊆ @α B
----------------[-2]
A ⊆ B●intersection-right
A ⊆ B & C
------------------[-1]
A ⊆ B, A ⊆ C●intersection-left
α=>A & α=>B ⊆ α=>C
------------------------------[-1]
α=>X ⊆ α=>C
最後の「α=>X」のところをちゃんとやる必要がある。
それと次は「すぐに偽だとわかる」ケース。
A+u ⊆ B
[u!∈A, u!∈B] -----------
false