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.
1 | fun distMoved (f : {x:real,y:real}->{x:real,y:real}, |
那么函数 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.
1 | fun flipGreen p = {x=~p.x, y=~p.y, color="green"} |
如上例,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.
1 | fun flipX_Y0 p = {x=~p.x, y=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 (共变) 的。