1. 程式人生 > >programming-languages學習筆記--第10部分

programming-languages學習筆記--第10部分

programming-languages學習筆記–第10部分

programming-languages學習筆記–第10部分

目錄

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

結合泛型和子類化,就是有界多型。

作者: ntestoc

Created: 2019-01-08 二 23:34