Presentation on theme: "Types for Units of Measure Andrew Kennedy Microsoft Research."— Presentation transcript:
Types for Units of Measure Andrew Kennedy Microsoft Research
Motivation zTypes catch errors in programs zPrograms written in type-safe programming languages cannot crash the system zBut there are errors that (currently) they dont catch: yout-of-bounds array accesses ydivision by zero ytaking the head of an empty list yadding a kilogram to a metre zAim: to show that units of measure can be checked by types.
Approaches to the problem zWhy not emulate using existing type systems? yBecause theres no support for the algebraic properties of units of measure (e.g. m s -1 = s -1 m) zBetter: add special units types to the language and type-check w.r.t. algebraic properties of units. yBut what about generic functions (e.g. mean and standard deviation of a list of quantities). What types do they have? zBetter still: a polymorphic type system for units of measure.
Types with units Floating-point types are parameterised on units e.g. m : kg num a : (m/s^2) num force : (kg*m/s^2) num Arithmetic operations respect units of measure e.g. force := m*a force := m+a
Units vs Dimensions zDimensions are classes of interconvertible units e.g. ylb, kg, tonne are all instances of mass ym, inch, chain are all instances of length zWhy not work with dimensions instead? yWe could, but to support multiple systems of measurement wed need to keep track of units anyway yTo keep things simple, we stick to units and assume that distinct units are incompatible (so no conversions) yAssume some set of base units from which all others are derived (e.g. kg, m, s)
Polymorphism Take ML/Haskell as our model, where functions are parametric in their types e.g. length : 'a list -> int map : ('a -> 'b) -> ('a list -> 'b list) Parameterise on units instead of on types: mean : 'u num list -> 'u num variance : 'u num list -> ('u^2) num
Arithmetic Now the built-in arithmetic functions can be assigned polymorphic types: + : 'u num * 'u num -> 'u num - : 'u num * 'u num -> 'u num * : 'u num * 'v num -> ('u*'v) num / : 'u num * 'v num -> ('u/'v) num bool sqrt : ('u^2) num -> 'u num sin : 1 num -> 1 num (angles are dimensionless ratios) zCuriosity: zero should be polymorphic (it can have any units), all other constants are dimensionless (they have no units).
Formalising the type system zIn the usual way, taking ML and adding: ysyntax for base units (baseunit) and unit variables (unitvar) ya new syntactic category of units: unit ::= 1 | unitvar | baseunit | unit *unit | unit -1 yother powers of units and the / syntax as derived forms yequations that define the algebra of units as an Abelian group: u * v = v * u(commutativity) u * (v * w) = (u * v) * w(associativity) u * 1 = u(identity) u * u -1 = 1(inverses)
zJust add: where = E is the equational theory of Abelian groups over units of measure lifted to type expressions. zExtend the usual rules for polymorphism introduction & elimination to quantify over unit variables. New typing rules
Type inference ML and Haskell have the convenience of decidable type inference: if the programmer omits types then the type checker can infer them e.g. fun head (x::xs) = x is assigned the type 'a list -> 'a Fortunately the same is true for units-of-measure types e.g. fun derivative (h,f) = fn x => (f(x+h) - f(x-h)) / (2.0*h) is assigned the type 'u num * ('u num -> 'v num) -> ('u num -> ('v/'u) num)
Principal types zThe units type system has the principal types property: if e is typeable there exists type τ such that all valid types can be derived by substituting unit expressions for unit variables in τ. ymoreover, the inference algorithm will find the principal type. If type checking e produces a type that instantiates to τ write zThe correctness of the algorithm is expressed as: ySoundness: yCompleteness:
The inference algorithm ML type inference uses a unification algorithm that, for any two types τ 1 and τ 2 finds a unifying substitution S (if one exists) such that S( τ 1 ) = S( τ 2 ). Moreover, it will find the most general unifier. zWe want more: unification under the equational theory of Abelian groups. zFortunately, unification in this theory is unitary (mgus exist) and decidable (theres an algorithm to find them).
The inference algorithm, cont. zUnfortunately, thats not all. To type let x = e 1 in e 2 usually one finds a type for e 1 and then quantifies on the variables that are free in its type but not present in the type environment. zThis is sound but not complete for inference of units of measure. zFix: first normalise the types in the type environment, a procedure akin to a change of basis.
Normal forms for types In ML, the principal type can be presented in more than one way, but only with respect to the names of type variables e.g. 'a * 'b -> 'a 'f * 's -> 'f Principal units types can have many non-trivial equivalent forms e.g. 'u num * ('u num -> 'v num) -> ('u num -> ('v/'u) num) 'u num * ('u num -> ('u*'v) num) -> ('u num -> 'v num) zIts desirable to present types consistently to the programmer. Fortunately every type has a normal form that corresponds to the Hermite Normal Form from linear algebra.
Semantics of polymorphism zThe polymorphic type of a function says something about the behaviour of the function. This is idea has become known as parametricity and is very powerful. zExamples: yif f : 'a list -> int then f cannot look at the elements of the list, so f (xs) = g (length(xs)) for some g : int -> int. yif f : 'a -> 'a then f must be the identity function (or else it diverges or raises an exception). ythere are no total functions with type int -> 'a yin the polymorphic lambda calculus, T is isomorphic to (T -> 'a) -> 'a.
Semantics of units polymorphism zParametricity is about representation independence: a polymorphic function is invariant under changes to the representation of its polymorphic arguments. zThe analogue for units is dimensional invariance: a polymorphic function is invariant under changes to the units of measure used for its polymorphic arguments. zThe idea can be formalised using binary relations to give a parametricity theorem in the style of Reynolds.
Consequences zTheorems for free e.g. if f : 'u num -> ('u^2) num then f (k*x) = k*k*f(x) for any positive k zThere are types for which no non-trivial expressions can be defined e.g. if only the usual arithmetic primitives are available (+ - * /), then any expression of type ('u^2) num -> 'u num does not return a non-zero result for any argument.
Dimensional analysis zOld idea: given some physical system with known variables but unknown equations, use the dimensions of the variables to determine the form of the equations. Example: a pendulum. θ m l g period t
Worked example Pendulum has five variables: mass m M length l L gravity g LT -2 angle θ none time period t T Assume some relation f(m, l, g, θ, t) = 0 Then by dimensional invariance f(Mm, Ll, LT -2 g, θ, Tt) = 0 for any "scale factors" M,L,T Let M=1/m, L=1/l, T=1/t, so f(1,1,t 2 g/l, θ, 1) = 0 zAssuming a functional relationship, we obtain
Dimensional analysis, formally Pi Theorem. Any dimensionally-invariant relation f(x 1,…,x n )=0 for dimensioned variables x 1,…,x n whose dimension exponents are given by an m by n matrix A is equivalent to some relation g(P 1,…,P n-r )=0 where r is the rank of A and P 1,…,P n-r are dimensionless products of powers of x 1,…,x n. Proof: Birkhoff.
Dimensional analysis New idea: express Pi Theorem by isomorphisms between polymorphic functions of several arguments and dimensionless functions of fewer arguments. e.g. 'M num * 'L num * ('L/'T^2) num * 1 num -> ('T^2) num is isomorphic to 1 num -> 1 num
What's left? zExtending the system to support multiple systems of units and automatic insertion of unit conversions zGeneralising some of the semantic results (e.g. a Pi Theorem at higher types) zUsing the parametric relations to construct a model of the language that accurately reflects semantic equivalences (i.e. is fully abstract wrt underlying semantics) zPractical implementaion in real languages