---
# System prepended metadata

title: 部分的型づけそる場

---

# 部分的型づけそる場

## 前提

Lit と and / or を含む (intersect と union を表す)

S, T = Top | Bottom | T -> T | or (Tn) | and (Tn) | int | num... | 1 | 2 ... | true | false

VS, VT = Top | Bottom | VT -> VT | ... | x (型変数)

における型づけ。

subtyping の計算は型変数を含まない T でのみできるとする

subtyping の計算

or (Tn) 


Constraint

VT <: VT

のセットについて解決を試みる。

## 基本的な考えかた

cts : Set [Constraint]

を受け取る

### 1. cts の中身を適切に分解し、最大限 x <: VT または VT <: x という形に帰着させる

基本的な分解操作の一覧
- VS <: and (VTn)
→ n について VS <: VT_n 
- or (VSn) <: VT
→ n について VS_n <: VT
- (VS1 -> VS2) <: (VT1 -> VT2)
→ VT1 <: VS1 と VS2 <: VT2

これらを施すと次のような形に帰着する (？)

i. 両辺とも T ← 嬉しい！
ii. 右辺か左辺が x で、もう片方が VT ← わりと嬉しい！
iii. 右辺が or で, 左辺が x でない
- VS <: or (VTn)

iv. 左辺が and で, 右辺が x でない

- and (VSn) <: VT

v. 片方の辺が VT の func type で、もう片方の辺が x でも func でも and/or でもない, したがって下のどれかになる

- VS1 -> VS2 <: int/num... /0/1 ...
- int/num...0/1/... <: VS1 -> VS2
- VS1 -> VS2 <: Top/Bottom
- Top/Bottom <: VS1 -> VS2


### 2. cts 矛盾チェック

i の場合は決定的に subtyping のチェックができる (本当に？)
v の場合も同様

ii の場合の特殊な場合として、 x <: x があげられる。この場合は矛盾を起こさないので OK！ → チェック済みとする

これによって矛盾が起きたら cts は矛盾しているものとしてブランチを棄却
これによってチェックしたものは cts から消す

### 3. 境界の計算と境界条件の伝播

前の作業によって ii, iii, iv の場合のみが残っている

ここで、ii (つまり片方が x のもの) を使って型境界を計算する

下限と上限を全て集めると次のようになる

{下限の型...} <: x <: {上限の型...}

なお、iii, iv および (ii の変数でない方)に x がある可能性が残っているので、この下限、上限を満たせば必ず型解決できるわけではない

※iii, iv の場合はダメなのはわかりやすいが ii の場合は次のようなものがある

x <: number
(1 -> numebr) <: y <: (x -> number)

このセットでは、x ~ 1 なら OK だが x ~ number なら矛盾である

さて、計算した下限 VS_n, VT_n について、次のような Constraint を新たに cts に追加する

or (VS_m) <: and (VT_n)  # ここで normalize が効きそう

(なお、すでに追加しているもの、自明に矛盾なものはその限りでない)
また、x に関係する制約を
or (VS_m) <: x と

x <: and (VT_n) のみに統一する。

### 4. 自明な代入と cts の refinement

上限と下限に同じ式が含まれているなら、x に代入する。

1 ~ 4 を変化がなくなるまで繰り返す

### 5. ブランチの分岐 → 分岐できない場合は 7 へ

次のような形の Constraint が残っている

ii. 右辺か左辺が x で、もう片方が VT
iii. 右辺が or で, 左辺が x でない
iv. 左辺が and で, 右辺が x でない


ここで ii を二つに分解して考える

ii(a). 右辺か左辺が x で、もう片方がTop, Bottom, 変数, 1, 2... , num, int,... のような一回の型
ii(b), 右辺か左辺が x で、もう片方がfunction (なお、and / or は iii, iv および分解で排除される)


このうち、iii, iv, ii(b) について、次のように cts を分解する

#### ii(b) の場合

cts を cts1 と cts2 にコピーする

x <: VS -> VT の場合
x は Bottom か関数型である必要がある。
- cts1 では x に Bottom を代入する
- cts2 では新しい変数 y, z に対し x に y -> z を代入する

VS -> VT <: x の場合
x は Top か関数型である必要がある
- cts1 では x に Top を代入する
- cts2 では新しい変数 y, z に対し x に y -> z を代入する

もとの Constraint は削除

#### iii の場合

x <: or (VTn) となっている

n 個の cts を作成し、それぞれ x <: VTn を制約として追加する

もとの Constraint は削除

#### iv の場合

iii と同様

### 6. 分岐した cts の計算

分岐したそれぞれについて solve し、矛盾がないブランチが見つかったなら矛盾なし、すべて矛盾があった場合、矛盾とする

### 7. 矛盾 / 非矛盾の判定

すでに ii(b) しか残っていない。すなわち Top, Bottom, x, lit, prim 間の制約に帰着している。

4 の制約伝播によって、この時点で矛盾がなければ矛盾がないとしてよい (未証明、要検証、または反例求)
　→ ChatGPT はサイクルが無ければ問題ないと言っています！　でも 4 でサイクル消える気がする y <: x <: y となったとき x <= y と代入されるので

## 補遺

### Normalize について

各種 and/or を取る操作において、より単純な形に変換した方が良い結果を生む。次のような変換を行う

VT | Bottom = VT
VT | Top = Top
VT | VT = VT
VT & Bottom = Bottom
VT & Top = VT
VT & VT = VT

T1 | T2 where T1 <: T2 = T2 (subtyping を計算するので、変数を含まない型のみ)
T1 & T2 where T1 <: T2 = T1

分配法則 (or に寄せる) (パフォーマンス悪化の可能性あり？) (逆変換の方が良いか　共通部分見つけるのダルそうだけど)

VT1 & (VT2 | VT3) = (VT1 & VT2) | (VT1 & VT3)


関数化 (関数の分解法則が使える可能性が上がる？)

(VT1 -> VT2) | (VT3 -> VT4) = (VT1 & VT2 -> VT2 | VT4)
(VT1 -> VT2) & (VT3 -> VT4) = (VT1 | VT2 -> VT2 & VT4)


例えば左辺なら | にして右辺なら 関数にする (& も同様) とかいいかも　分解規則をできるだけ使いたい


吸収

VT1 & (VT1 | VT2) = VT1

VT1 | (VT1 & VT2) = VT1

バックエンドは JavaScript で、基本的に

(A -> B) | (C -> D) の意味としては 「A -> B または C -> D という関数型入っている」で、ここに型変換はからまないので、この関数に A & B を適用して C | D を得ることは合法。 逆に (A & B) -> (C | D) も (A -> B) | (C -> D) として見ることが出来る (外延的な等価) JavaScript の instanceof などの使用は制限するのでこれらの型は等しくなる

ブランチングは特殊。 A <: distinguishable なら、branch : A | B -> (A -> C) -> B | C ができる。