-
Notifications
You must be signed in to change notification settings - Fork 14
Subtyping and Variance
Georges Dupéron edited this page Sep 27, 2017
·
2 revisions
Unofficial/unsupported notes (i.e. changes to the implementation may affect what follows):
To extend a language with subtyping, one needs to:
- override
current-typecheck-relation, which seems to be the⊑relation, possibly using variances to automatically derive a subtyping relation between the existing type constructors - make sure all type constructors properly use
#:arg-variances - override
current-join, using variances in the same way - possibly override
current-check-relation? - For the languages
mlish.rktandinfer.rkt, it would be desirable to extend inference of polymorphic arguments so that it works as expected without the need to explicitly up-cast arguments (I (@jsmaniac) am working on something formlish.rkt, ping me for more info).
- The documented
#:arg-variancesallows a type declared usingdefine-type-constructorto compute the variance for each argument position. -
get-arg-variancesis implemented in typecheck.rkt. - When considering a type
#'(tycons τ₁ … τₙ), the variance computed by the#:arg-variancesoption is stored on the#'tyconsidentifier itself, as a syntax property. - Calling
(syntax-parse τ [(tycons τ ...) (get-arg-variances #'tycons)])will retrieve the list of variances originally computed by the#:arg-variances. - The variance struct is a
#:prefabstruct, so it can safely be embedded into syntax objects (this makes it easier to call(syntax-parse (list τ₁ τ₂ the-variance) […] …), without the risk of creating 3D syntax) - The variance struct contains two fields, accessible via
variance-covariant?andvariance-contravariant?. - The other two cases are
variance-invariant?(i.e. both fields are#f) andvariance-irrelevant?(i.e. both fields are#t, I suspect this can only happen for phantom type variables which do not appear in the actual type, and similar situations) -
variance-join(Variance Variance -> Variance) performs a conservative join of two variance constraints. The result will be covariant if and only if both arguments were covariant. The result will be contravariant if and only if both arguments were contravariant. -
variance-compose(Variance Variance -> Variance) computes the variance of ax-variant position occurring within ay-variantposition. For example in(→ (→ ? Int) String), the type?is in a contravariant position of the inner→, which itself occurs in a contravariant position of the outer→, therefore the?position is covariant in the overall type. As expected,(variance-compose contravariant contravariant)will returncovariant. Generally speaking, acontravariantflips the other argument's variance if the other argument is eithercovariantorcontravariant.invariantis unaffected by the operation (i.e. if either argument isinvariant, the result isinvariant).irrelevantabsorbs the other argument, I'm not sure why.