14 Exceptions

Download Report

Transcript 14 Exceptions

14. Exceptions
cocoa
Exception のモデル化
• 性質
– Exception は現在の実行を中断してより上位の
context に実行を移す
• 定義
– Exception を投げたことを表す項 error
– 評価規則
• error t → error
• v error → error
– Typing rule
• Γ|- error : T --- exception は任意の型でよい
Call-by-value の評価順を尊重し
ているのはなぜか?
• 確かに、t error → error という定義でも
結果は変わらない。
• しかし、reference が入ったり fix が導
入されると結果が変わるうる。
– (fix (λx:Nat.x)) error は止まらない
任意の型となる exception
• Exception は任意の context に適用されうる
– (λx:Nat.x) error where error : Nat
– error (λx:Bool.x)
• where error : (Bool -> Bool) -> T
• 任意の型を表す型
– Chapter 23: ∀X.X (parametric polymorphism)
– Section 15.4: Bottom (subtyping)
– ocaml : exn と raise
exception A
A : exn
raise : exn -> ‘a
任意の型は気持ちが悪いので error の
型を ascribe すればいいんじゃない
の?
• 少なくとも naïve にやるとまずい
(lambda x:Bool.3)(error as Bool) : Nat
→ (error as Bool) : Nat
Exception によって何が変わっ
た?
• Progress 定理を変更する必要がある。
– A closed, well-typed term evaluates to a
value of the same type or error
• term は唯一の型を持つという性質が失わ
れる。
Try-catch(try-with) のモデル
化
• まず try-節を評価する
t1 → t1’
try t1 with t2 → try t1’ with t2
• Exception が投げられなかった時はその
まま
try v1 with t2 → v1
• 投げられたときは捕らえる
try error with t2 → t2
Try-with の型
• とても自明である
Γ|- t1 : T Γ|- t2 : T
Γ|- try t1 with t2 : T
Exception が値を渡せるように
しよう
• 値を持った exception という term
raise t
• 評価規則
(raise v1) t2 → (raise v1)
v1 (raise v2) → (raise v2)
raise (raise v) → (raise v)
t1 → t1’
raise t1 → raise t1’
では (raise v)の型はどうする?
• Nat や String にしよう
– C では errno で error code を表している
• Variant にしよう
– T_exn = < divideByZero : Unit,
overflow : Unit,
fileNotFound : String, … >
– 以後はレジュメ参照
15. Subtyping
cocoa
Motivation
• Record, variant, object などを考えると
今までの型システムは厳密すぎる。
Ex. (lambda r:{x:Nat}. r.x + 1) {x = 0, y = 1}
この term は実行時エラーを起こさないが、
well-typed ではない。
Subtyping の基本
• Principle of safe substitution
S <: T ならば T の値を S の値で置き換えても
安全である。
{x=0} を {x=0,y=1} で置き換えても型安全
• Subset semantics
S <: T ならば S の値の集合は T の値の集合の
subset である。(したがって置き換えてもok)
Record 型の subtyping
• 要素を増やしても subtype
Γ|- {x:Nat,y:Nat} <: {x:Nat}
• 要素同士が subtype なら subtype
Γ|- S <: T
Γ|- {x:S} <: {x:T}
Variant 型の subtyping
• 要素が少ないと subtype
– v : <x:Nat,y:Nat> --- v は x か y の可能性が
ある
– u : <x:Nat> --- u は x の可能性がある
– v を u で置き換えても型安全
Γ|- <x:Nat> <: <x:Nat,y:Nat>
• 要素同士が subtype なら subtype
Γ|- S <: T
Γ|- <x:S> <: <x:T>
関数型の subtyping
(λr:{x:Nat}. r.x) {x:10,y:3}
この関数を
(λr:{x:Nat,z:Nat}. r.x + r.z) で置き換える
のは安全ではない
– Γ|- {x:Nat,z:Nat} -> Nat <: {x:Nat} -> Nat
はなりたたない
– Γ|- {x:Nat} -> Nat <: {x:Nat,z:Nat} -> Nat
は成り立つ
Contravariance
Γ|- {x:Nat} -> Nat <: {x:Nat,z:Nat} -> Nat
この関係は record 型の subtype 関係
Γ|- {x:Nat,z:Nat} <: {x:Nat}
と逆になっている。
Γ|- T <: S
Γ|- S’ <: T’
Γ|- S -> S’ <: T -> T’
T0 <: T1 <: T2 <: … と続く列は
存在するか?
• Record 型の場合
– (要素同士の subtyping を考えない場合)存在
しない
• {} でおしまい
• Variant 型、関数型の場合
– 存在する
• {x:Nat} -> Nat <: {x:Nat,y:Nat} -> Nat <: …
Inversion of subtype relation
• Subtype 関係は値の種類を保存する
– 関数型の subtype も関数型
– Record 型の subtype は record 型
(Proof. By induction on subtyping
derivations)
重要な性質は保存される
• すべて成立
– Substitution lemma
– Preservation theorem
– Progress theorem
The Top type
• Top 型
– すべての型の supertype
• Γ|- S <: Top for any S
– Subtyping を含む型システムでしばしば用い
られる
– Top 型を加えても体系の性質はほとんど変わ
らない
– 主に技術的な理由により用いられる
The Bottom type
• Bottom 型 (void 型)
– すべての型の subtype
• Γ|- Bot <: T for any T
– 要素を持たない
• Bot <: Nat -> Nat, Bot <: {x:Nat} が成り立つが、
ここで inversion of subtype relation を考えよう
• 要素を持たないので値を返さない操作の型に使え
る (raise)
– Typechecker を複雑にしてしまう
• Γ|- ts : T であっても t が関数型とは限らない
Up-casting
• [Java] すべての値(数を除く)は Object
型と思って問題ない
• Up-casting を加えても体系にまったく影
響はない
Γ|- t : S
S <: T
Γ|- t : T
Γ|- t as T : T
Down-casting
• Poor-man’s polymorphism
– Java では List, Hash, Set の要素は Object なので
要素を取り出すときに down-casting が必要
– 静的に型を保証できない上に、実行時にもコストが
かかる
• これを克服するため Pizza, GJ, PolyJ などの提案がある
– でもたしか Pizza の実装は down-casting を使ってたような
– Reflection, dynamic class-loading などを考えると仕
方がない面もある
References
Γ|- S <: T
Γ|- Ref S <: Ref T
• とやるとまずい
Let r : Ref {x:Nat} = ref {x=1} in
(r as Ref {}) := {};
(!r).x
• 要素の subtyping を行ってはいけない
Arrays
• Java では
Γ|- S < T
Γ|- Array S < Array T
となっている
• これだと書き込み時に型チェックが必要
void foo( Object a[] ) { a[0] = new Integer(1); }
void bar() { String a[] = new String[3]; foo (a); }
• Benjamin 曰く「a flaw in the language
design」
Coercion semantics (1/2)
• 今までの前提
– Subtyping は型システムを柔軟にするためで、
evaluation は変わらない
• 今までの前提の問題点
– 実行効率がおそろしく悪い
• Subtyping がある場合 λr. r.x をどのようにコンパ
イルできるだろうか?
• Floating 命令は整数も扱える必要がある (Int <:
Float)
Coercion semantics (2/2)
• Subtyping のあるシステムから subtyping
のないシステムへの変換を行う
– メリット
• Subtyping のあるシステムの持つオーバヘッドが
具体的になる
– 方針
• Subsumption rule を何とかすればよい
Γ|- t : S S <: T
Γ|- t : T
• S から T への変換がわかればよい
Translation
• 基本的アイデア
– S <: T の derivation から S から T への変換
関数を作る
• [[T <: T]]
= λx:[[T]].x
• [[{x:Nat,y:Nat} <: {x:Nat}]]
= λr:{x:Nat,y:Nat}.{x=r.x}