programming-languages學習筆記--第10部分
programming-languages學習筆記–第10部分
目錄
- 1. Subtyping
- 2. 子類關係
- 3. Depth Subtyping
- 4. Function Subtyping
- 5. OOP中的子類化
- 6. 泛型對比子類化
- 7. Bounded Polymorphism
1 Subtyping
- 偽程式碼表示:
建立record: {f1=e1, f2=e2, …, fn=en}, 欄位訪問:e.f,欄位更新:e1.f=e2
基本的型別系統: {f1:t1, f2:t2, …, fn:tn}
a:{x:real, y:real}與型別 b:{x:real, y:real, color:string}不同,但是可以在接受第一種型別的地方使用第二種型別。 讓使用a的地方用b代替通過型別檢查。就是Subtyping。
2 子類關係
保持subtyping獨立,一個程式語言已經有很多型別規則,不去修改它們,只增加subtyping。 用t1 <: t2(型別間的二元關係)表示t1是t2的子型別,如果e擁有型別t1並且t1 <: t2,則e也擁有型別t2。
如果t1 <: t2,則t1型別的任何值都可以用在t2可以使用的地方。
3 Depth Subtyping
深度子類化: {center:{x:real,y:real}, r:real} <: {center:{x:real,y:real,z:real}, r:rael} 如果要讓這個子類化成立,則需要新增規則, if ta <: tb then {f1:t1,…,f:ta,…,fn:tn} <: {f1:t1,…,f:tb,…,fn:tn} 但是它破壞了可靠性(soundness),可以訪問不存在的欄位。
如果欄位是不可變的,則深度子類化是可靠的,只能從3個裡面選2個:setters,depth subtyping, soundness。
4 Function Subtyping
函式型別,在higher-order函式中,引數可以用使用t3->t4代替t1->t2麼?
函式返回值是可以的: if ta <: tb then t->ta <: t->tb 函式返回值是協變(covariant)的。
函式引數不可以: ta <: tb 不允許 ta->t <: tb->t, 相反的情況可以: if tb <: ta then ta->t <: tb->t, 引數型別是逆變(contravariant)的。
可以綜合起來: if t3 <: t1 and t2 <: t4, then t1->t2 <: t3->t4。 引數是逆邊,返回值是協變。
5 OOP中的子類化
子類關係就是子型別關係。
一個物件就是包含欄位和方法的記錄:
- 可變欄位
- 方法是可變函式,並且可以訪問self
可以設計一個像記錄型別的型別系統:
- 子型別可以有額外的欄位和方法
- 覆蓋方法需要逆變引數和協變返回值,與函式子類化相似。
slef/this是特殊的,雖然是函式引數,但它是協變的。子類中的方法只能使用子類可用的欄位和方法。
6 泛型對比子類化
在ML中:
fun compose (g,h) = fn x => g (h x) (* val compose = fn : ('a -> 'b) * ('c -> 'a) -> 'c -> 'b *)
子類化不適合這樣的操作,作為容器不方便。 需要做downcast,並且需要執行時開銷。
子類化適用於表示幾何,GUI等。
7 Bounded Polymorphism
結合泛型和子類化,就是有界多型。
Created: 2019-01-08 二 23:34