# Subtyping for Functions

To obtain lambda calculus with subtyping, we modify only primitive rules if needed and the application rule for Simple Types for Lambda Calculus.

We modify application rule to allow not only arguments of exact type, but also of subtype:

This modification alone allows us to write e.g.

let (f:int->int) = (%x:int. x + 1) in let (p:pos) = 5 in f p

However, it does not allow us to type check code like this:

let (twice:(int -> int)->int) = (% f. f (f 5)) in let (g:(int->pos)) = (%x:int. 42) in twice g

For this purpose, we can define subtyping relation on function types by adding the rule

The new application rule then follows as a consequence

We say that

- function result is
**covariant**(behaves same as function type) - function argument is
**contravariant**(behaves opposite of the function type)

Contravariance of argument may seem surprising at first, but it is the right thing:

- compare to modified application rule - is subtype of , we weakened argument to strengthen type of
- consider interpretation of as a logical implication, and note that in propositional logic the subtyping relation on function types becomes a tautology
- ultimate answer is in soundness proof

## Method Overriding

Rules for function types justify rules for overriding methods

- in subtype class, the type of overriden function has a subtype
- it can have weaker argument types and stronger result type