A combinatorial view of module composition for OO programming languages Ugo de Liguoro University of Turin Dagstuhl, June 2014
Components in OO programming Object based: a library is just collection of objects that can be cloned and updated at run time Class based: a class hierarchy which is either a tree (single hineritance) or a DAG (multiple inheritance) of class declarations Mixin based: mixins are parametric sub-classes; classes are obtained by linearization of mixins composition Trait addition: traits are stateless records of methods that can be added to a class without overriding methods in the class with the same name
Modeling components Objects and classes represented by means of typed λ-calculus with records (Cardelli-Wegner, Bruce, Fisher-Honsel-Mitchell) A calculus of objects (Abadi-Cardelli) Classes and mixins via typed and typefree λ-calculus (Bracha-Cook) Formalization in idealized Java (Igarashi-Pierce-Wadler)... Advantages: safety properties (exclusion of method not understood errors), discovery and clarification of subtle ambiguities end problems (self reference and mytype, inheritance vs. subtyping, binary methods) Drowbacks: very complex type systems, using recursive types, second order universal and existential quantifiers, F-bounded polymorphism,...
An alternative direction represent OO entities by a suitable extension of type free λ-calculus use intersection types as a finitary representation of semantic properties find a combinatory factorization of OO module composition dl01 U. de Liguoro: Characterizing Convergent Terms in Object Calculi via Intersection Types. LNCS 2044: 315-328(2001) dl02 U. de Liguoro: Subtyping in Logical Form. ENTCS 70 (2002) vbdl08 S. van Bakel, U. de Liguoro: Logical Equivalence for Subtyping Object and Recursive Types. Theory Comput. Syst. 42(3): 306-348 (2008) dlc14 U. de Liguoro, T-C. Chen: Semantic Types for Classes and Mixins, ITRS 2014 to appear and related works RvB14 R. Rowe, S. van Bakel: Semantic Types and Approximation for Featherweight Java, TCS, 517 (2014) 3474 BDDM14 J. Bessai, B. Düdder, A. Dudenhefner, M. Martens: Delegation-based Mixin Composition Synthesis, ITRS 2014 to appear
The calculus Λ R Terms: M,N ::= x λx.m MN R M.a M R (term) R ::= a = M a a A (record) If A = then we get the empty record Reduction: (β) (λx.m)n M{N/x} (R 1 ) a = M a a A.b M b if b A (R 2 ) a = M a a A b = N b b B a = M a, b = N b a A\B,b B
Intersection types σ,τ ::= α ω σ τ σ τ a : σ with denumerably many type variables α TypeVar. We define a preorder s.t. plus ω is top, meet σ ω ω ω (σ τ) (σ ρ) σ (τ ρ) σ σ,τ τ = σ τ σ τ σ τ = a : σ a : τ a : σ a : τ a : σ τ a : σ (from [BDDM14])
Semantics If η : TypeVar 2 Λ0 R, where Λ 0 R is the set of closed Λ R -terms [[α]] η [[ω]] η [[σ τ]] η = η(α) = Λ 0 R = {M Λ 0 R M. M λx.m & N [[σ]] η. M {N/x} [[τ]] η } [[ a : σ ]] η = {M Λ 0 R R. M R & R.a [[σ]] η } [[σ τ]] η = [[σ]] η [[τ]] η
Semantics If η : TypeVar 2 Λ0 R, where Λ 0 R is the set of closed Λ R -terms [[α]] η [[ω]] η [[σ τ]] η = η(α) = Λ 0 R = {M Λ 0 R M. M λx.m & N [[σ]] η. M {N/x} [[τ]] η } [[ a : σ ]] η = {M Λ 0 R R. M R & R.a [[σ]] η } [[σ τ]] η = [[σ]] η [[τ]] η
Semantics If η : TypeVar 2 Λ0 R, where Λ 0 R is the set of closed Λ R -terms [[α]] η [[ω]] η [[σ τ]] η = η(α) = Λ 0 R = {M Λ 0 R M. M λx.m & N [[σ]] η. M {N/x} [[τ]] η } [[ a : σ ]] η = {M Λ 0 R R. M R & R.a [[σ]] η } [[σ τ]] η = [[σ]] η [[τ]] η
Semantics If η : TypeVar 2 Λ0 R, where Λ 0 R is the set of closed Λ R -terms [[α]] η [[ω]] η [[σ τ]] η = η(α) = Λ 0 R = {M Λ 0 R M. M λx.m & N [[σ]] η. M {N/x} [[τ]] η } [[ a : σ ]] η = {M Λ 0 R R. M R & R.a [[σ]] η } [[σ τ]] η = [[σ]] η [[τ]] η then σ τ = η. [[σ]] η [[τ]] η
Type assignment To BCD rules (Ax) Γ,x : σ x : σ (ω) Γ M : ω Γ,x : σ M : τ Γ λx.m : σ τ ( I) Γ M : σ τ Γ N : σ ( E) Γ MN : τ Γ M : σ Γ M : τ ( ) Γ M : σ τ Γ M : σ σ τ ( ) Γ M : τ where Γ = {x 1 : σ 1,...,x k : σ k } and Γ,x : σ = Γ {x : σ}
Type assignment... we add Γ M : a : σ Γ M.a : σ If we abbreviate Γ M : σ a B Γ a = M,b = N b b B : a : σ a : σ a a A a A a : σ a then we get σ b τ b b B A hence a : σ a a A b : τ b b B Γ M b : σ b b B A Γ a = M a a A : b : σ b b B
Type invariance 1. Γ M : σ & M N = Γ N : σ (subject reduction) 2. Γ N : σ & M N = Γ M : σ (subject expansion)
Type invariance 1. Γ M : σ & M N = Γ N : σ (subject reduction) 2. Γ N : σ & M N = Γ M : σ (subject expansion)
Soundness theorem A closed substitution is a map θ : TermVar Λ R Then θ,η = Γ = {x 1 : σ 1,...,x k : σ k } def θ(x i ) [[σ i ]] η i = 1,...,k Γ M : σ & θ,η = Γ = Mθ [[σ]] η where Mθ M{θ(x 1 )/x 1 }...{θ(x k )/x k }
Objects and the typing of self (this) According to the self-application representation, an object is a record O a = λt.m a a A where a = λt.m a is the method labelled by a Define (O a) (O.a)O then (O a) (λt.m a )O M a {O/t} hence t is the self (this) variable. If t fv(m a ) then M a {O/t} M a, and we say that a = λt.m a is a field
Objects and the typing of self (this) For any method a = λt.m O we have the typing Γ,t : σ M : τ Γ λt.m : σ τ Γ O : a : σ τ In particular if a = λt.m O is a field then t fv(m) and Γ,t : ω M : τ Γ λt.m : ω τ Γ O : a : ω τ Note that a : ω τ a : σ τ but in general
Objects and the typing of self (this) Recalling that (O a) (O.a)O we have the derived rule Γ O : a : σ τ Γ O : σ Γ O a : τ that also implies Γ O : a : σ τ σ. However if O a = λt.1, b = λt.(t a)+1 then O : a : ω odd,b : a : ω even odd even if O : a : ω even i.e. the typing of the self (this) is just conditional
Objects and the typing of self (this) Recalling that (O a) (O.a)O we have the derived rule Γ O : a : σ τ Γ O : σ Γ O a : τ that also implies Γ O : a : σ τ σ. However if O a = λt.1, b = λt.(t a)+1 then O : a : ω odd,b : a : ω even odd even if O : a : ω even i.e. the typing of the self (this) is just conditional
Typing rules for (merge) Define l( a = M a a A ) = A Γ M : Γ R : a : σ ( 1 ) Γ M R : a : σ Γ M : a : σ a l(r) ( 2 ) Γ M R : a : σ so that the following rule is admissible Γ M : a : σ a a A Γ R : b : τ b b B Γ M R : a : σ a,b : τ b a A\B,b B
Remark The following are not well formed terms: R x Λ R and hence λx.(r x) Λ R Otherwise set l(m) = if M is not a record, then Γ,x : σ R : a : τ a l(x) = Γ,x : σ R x : a : τ Γ λx. R x : σ a : τ Say that x fv(r) and take σ a : ρ and N s.t. Γ N : ρ and Γ N : τ then Γ (λx. R x) a = N : a : τ but Γ R a = N : a : τ
Extension and overriding For any record R define (R.a := N) R a = N then we have the rules Γ M : σ (upd 1 ) Γ R.a := M : a : σ Γ R : a : σ a b (upd2 ) Γ R.b := M : a : σ and therefore Γ a = N a a A : b : σ b b B B A Γ N : τ Γ a = N a a A.c := N : c : τ,b : σ b b B \{c}
Classes A class is a generator of objects with parameters: class Person field: name; method: display() { print(name); } which is formally Person λn. name = λt.n, display = λt.print(t name)
Inheritance A class can extend some fixed superclass(es) by inheritance: class Graduate superclass: Person; field: degree; method: display() {super.display(); print(degree);} that is Graduate λn.λd. name = λt.n, degree = λt.d, display = λt.(personn) display;print(t degree)
From class inheritance... Graduate λn.λd. name = λt.n, degree = λt.d, display = λt.(personn) display;print(t degree) is equivalent to λn. λd. (Personn) degree = λt.d, display = λt.(personn) display;print(t degree)
... to mixin inheritance λn. λd. (Personn) degree = λt.d, display = λt.(personn) display;print(t degree) that is equivalent to λn. λd. (λs. (s n) degree = λt.d, display = λt.(s n) display;print(t degree) ) Person
Mixins (after Cook and Bracha) A mixin is a parametric heir of a super-class: Definition mixin R, x where s = super def = λ x λs.(s R) fv(r) {s, x} Since any record R can be factored into R 1 R k, where k and the R i are not unique, we have that for any class C: C d 1 d k = ((mixin R1, d 1 ) (mixin Rk, d k )) where mixin Ri, d i (mixin Ri, x i ) d i for several choices of preexisting modules mixin Ri, x i
Typing mixins Set mixin Ri λx.(x R i ) where R 1 a = N 1, R 2 b = N 2, R 3 a = N 3 and assume x fv(r i ) then Γ,x : N 1 : σ 1 Γ,x : x : Γ,x : a = N 1 : a : σ 1 Γ,x : x a = N 1 : a : σ 1 Γ mixin R1 λx.(x a = N 1 ) : a : σ 1
Typing mixins R 1 a = N 1, R 2 b = N 2, R 3 a = N 3 x fv(r i ) and also Γ,x : b : σ 2 x : b : σ 2 b l( a = N 1 ) Γ,x : b : σ 2 x a = N 1 : b : σ 2 Γ mixin R1 λx.(x a = N 1 ) : b : σ 2 b : σ 2 therefore since a : σ 1 b : σ 2 a : σ 1 that is Γ mixin R1 : b : σ 2 a : σ 1 b : σ 2 b : σ 2 Γ mixin R1 : b : σ 2 a : σ 1,b : σ 2
Typing mixins R 1 a = N 1, R 2 b = N 2, R 3 a = N 3 x fv(r i ) Similarly for mixin R2 λx.(x R 2 ) assuming that Γ N 2 : σ 2 we have Γ mixin R2 : b : σ 2 so that Γ mixin R2 : b : σ 2 Γ mixin R1 : b : σ 2 a : σ 1,b : σ 2 Γ mixin R1 mixin R2 : a : σ 1,b : σ 2
Typing mixins R 1 a = N 1, R 2 b = N 2, R 3 a = N 3 x fv(r i ) If Γ N 1 : σ 1, Γ N 3 : σ 3 but Γ N 1 : σ 3 we have Γ mixin R3 : a : σ 3 and so that but Γ mixin R1 : a : σ 1 a : σ 3 a : σ 1 Γ mixin R1 mixin R3 : a : σ 1 Γ mixin R1 mixin R3 : a : σ 3
Traits (after Ducasse and others) A trait is a record of methods (not of fields) without any super-call Traits satisfy Methods defined in a class itself take precedence over methods provided by a trait A non-overridden method in a trait has the same semantics as if it were implemented directly in the class (flattening property) Composition order is irrelevant; all the traits have the same precedence, and hence conflicting trait methods must be explicitly disambiguated
Exclusive merge R,S ::= a = M a a A R S (record) a = M a a A b = N b b B a = M a, b = N b a A\B,b B \A Γ R : a : σ a l(s) ( 1 ) Γ R S : a : σ Γ S : a : σ a l(r) ( 2 ) Γ R S : a : σ
Classes from traits Any class C (forgetting about parameters) can be factored into ( k ) C = (T 1 T k ) R = mixin R T i i=1 where the T i are traits More radically we could say that C = a 1 = M 1,...,a n = M n ( n ) C = T i where T i a i = M i, namely unit traits made of just one method! i=1
The synthesis problem A tentative formulation of the synthesis by inhabitation problem: How complex could be a solution? T 1 : σ 1,...,T k : σ k? : τ T 1 a = 1 : a : odd, T 2 b = λt.(t.a+1) : b : a : odd even a : even odd Problem:? : a : even Solution: a = (T 1 T 2 ) b Problem:? : b : a : odd odd Solution: b = λt.((t a = (t b) ).a+1)
Challenges find a set of combinators including,,, mixin R, generating a combinatory algebra of modules s.t. given any set of traits T 1,...,T k, if C Λ R (T 1,...,T k ) is a class term then C d is equivalent (possibly the normal form of) to a term built only by the combinators in the algebra and the traits T i and d j extend the synthesis by inhabitation method to the algebra of modules try to apply the method to existing programming languages like Scala and Python, say via staged combinatory synthesis