函数子类型
Function Subtyping.
函数 (方法) 也拥有它的类型,因此研究函数类型间的 subtyping 关系也是很有必要的。It is just as important for understanding how to safely override methods in object-oriented languages.
When we talk about function subtyping, we are talking about using a function of one type in place of a function of another type.
我们以 higher-order function 为例研究函数类型间的 subtyping 关系:distMoved function computes the distance between the two-dimensional point p and the result of calling f with p.
fun distMoved (f : {x:real,y:real}->{x:real,y:real},
p : {x:real,y:real}) =
let val p2 : {x:real,y:real} = f p
val dx : real = p2.x - p.x
val dy : real = p2.y - p.y
in Math.sqrt(dx*dx + dy*dy) end
fun flip p = {x=~p.x, y=~p.y}
val d = distMoved(flip, {x=3.0, y=4.0})
那么函数 distMoved 的类型为 (({x:real,y:real}->{x:real,y:real}) * {x:real,y:real}) -> real.
函数 flip 的类型为 {x:real, y:real} -> {x:real, y:real},与函数 distMoved 期待的参数类型是相符的;以函数 flip 为参数调用函数 distMoved 没有用到 subtyping。
Convariant Return Type
The subtyping for the return types works covariant as for the types overall.
函数类型与其返回值类型的 subtyping 关系是 covariant (协变) 的: If ta <: tb, then t -> ta <: t -> tb.
fun flipGreen p = {x=~p.x, y=~p.y, color="green"}
val d = distMoved(flipGreen, {x=3.0, y=4.0})
如上例,flipGreen 函数作为参数传入 distMoved 函数不会产生任何问题。
flipGreen函数的返回值类型为{x:real,y:real,color:string},是distMoved形参函数返回值类型{x:real,y:real}的 subtype。- 而
flipGreen函数类型{x:real,y:real}->{x:real,y:real,color:string}是distMoved形参函数类型{x:real,y:real}->{x:real,y:real}的 subtype。
可以看出函数类型与其返回值类型 subtyping 的协变关系。
Contravariant Argument Type
The subtyping for argument types is the reverse of the subtyping for the types overall.
函数类型与其参数类型的 subtyping 关系是 contravariant (逆变) 的: If ta <: tb, then tb -> t <: ta -> t.
fun flipX_Y0 p = {x=~p.x, y=0}
val d = distMoved(flipX_Y0, {x=3.0, y=4.0})
如上例,flipX_Y0 函数作为参数传入 distMoved 函数不会产生任何问题。
flipX_Y0函数的参数类型为{x:real},是distMoved形参函数参数类型{x:real,y:real}的 supertype。- 而
flipX_Y0函数类型{x:real}->{x:real,y:real}是distMoved形参函数类型{x:real,y:real}->{x:real,y:real}的 subtype。
可以看出函数类型与其参数类型 subtype 的逆变关系。
The general rule for function subtyping is: If t3 <: t1 (argument type) and t2 <: t4 (return type), then t1->t2 <: t3->t4. This rule, combined with reflexivity lets us use contravariant arguments, covariant results, or both.
注意在 OOP 语言中,self (或 this) 是被特殊处理的,它的类型与对象的类型始终是 convariant (共变) 的。