Type Systems
Lecture 6 Nov. 24th, 2004 Sebastian Maneth
http://lampwww.epfl.ch/teaching/typeSystems/2004
Type Systems Lecture 6 Nov. 24th, 2004 Sebastian Maneth - - PowerPoint PPT Presentation
Type Systems Lecture 6 Nov. 24th, 2004 Sebastian Maneth http://lampwww.epfl.ch/teaching/typeSystems/2004 Today towards Featherweight JAVA 1. Objects 2. Simple Classes 3. Open Recursion through Self 4. Featherweight Java (FJ)
Lecture 6 Nov. 24th, 2004 Sebastian Maneth
http://lampwww.epfl.ch/teaching/typeSystems/2004
What is an OBJECT? a data structure, encapsulating some internal state, and offering access to it via a collection of methods. Internal state = mutable instance variables Consider our simply-typed λ-calculus with records (and Unit type, and sequences) and references. Allocation r ef t r = r ef 5 is of type Ref Nat Dereference ! t ! r is of type Nat Assignment t : =t ’ is of type Unit
OBJECT = a data structure, encapsulating some internal state, and offering access to it via a collection of methods. l et x = r ef 1 i n { get = λ_: Uni t . ! x, i nc = λ_: Uni t . x: =succ( ! x) } mutable instance variable methods
OBJECT = a data structure, encapsulating some internal state, and offering access to it via a collection of methods. l et x = r ef 1 i n { get = λ_: Uni t . ! x, i nc = λ_: Uni t . x: =succ( ! x) } mutable instance variable methods The type of the record c is { get : UnitNat, inc : UnitUnit } c =
evaluates to uni t : Uni t
Let Count er be the type { get : UnitNat, inc : UnitUnit } i nc3 i nc3 = λc: Count er . ( c. i nc uni t ; c. i nc uni t ; c. i nc uni t ) Takes an argument of type Count er (“a counter object”) and applies three times its i nc method. Can i nc3 i nc3 be applied to the following Reset Count er record? l et x = r ef 1 i n { get = λ_: Uni t . ! x, i nc = λ_: Uni t . x: =succ( ! x) , r eset = λ_: Uni t . x: =1}
Can you write a function that generates and returns a new counter object, each time it is called?
Sure! l et x = r ef 1 i n { get = λ_: Uni t . ! x, i nc = λ_: Uni t . x: =succ( ! x) } : Count er c = newCount er = λ_: Uni t . c : Uni t Count er Can you write a function that generates and returns a new counter object, each time it is called?
Can you write a function that generates and returns a new counter object, each time it is called? Sure! l et x = r ef 1 i n { get = λ_: Uni t . ! x, i nc = λ_: Uni t . x: =succ( ! x) } : Count er c = newCount er = λ_: Uni t . c : Uni t Count er nc = newCount er uni t
Group all instance variables into a record l et r = { x=r ef 1} i n { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . r . x: =succ( ! ( r . x) ) } : Count er c = Count er Rep = { x: Ref Nat } The representation type of the object.
newCount er = λ_: Uni t . c : Uni t Count er newReset Count er = λ_: Uni t . c : Uni t Reset Count er Reset Count er <: Count er How can we define a ResetCounter, using the definition of Counter?
Reset Count er <: Count er How can we define a ResetCounter, using the definition of Counter?
l et r = { x=r ef 1} i n { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . r . x: =succ( ! ( r . x) ) } : Count er l et r = { x=r ef 1} i n { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . r . x: =succ( ! ( r . x) ) r eset = λ_: Uni t . r . x: =1} : Reset Count er
Or rather, how to describe their common functionality?
l et r = { x=r ef 1} i n { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . r . x: =succ( ! ( r . x) ) } : Count er l et r = { x=r ef 1} i n { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . r . x: =succ( ! ( r . x) ) r eset = λ_: Uni t . r . x: =1} : Reset Count er
should NOT be shared!
l et r = { x=r ef 1} i n f ( x) : Count er
should NOT be shared! NOT f ( x) ! Cannot be in terms of x! Use the object’s representation type! Count er Rep = { x: Ref Nat } Or rather, how to describe their common functionality?
l et r = { x=r ef 1} i n { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . r . x: =succ( ! ( r . x) ) r eset = λ_: Uni t . r . x: =1} : Reset Count er
l et r = { x=r ef 1} i n count er Cl ass r : Count er count er Cl ass = λr : Count er Rep. { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . r . x: =succ( ! ( r . x) ) } : Count er RepCount er
How to define r eset Count er Cl ass in terms of count er Cl ass??
l et r = { x=r ef 1} i n count er Cl ass r : Count er count er Cl ass = λr : Count er Rep. { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . x: =succ( ! ( r . x) ) } : Count er RepCount er
How to define r eset Count er Cl ass in terms of count er Cl ass??
r eset Count er Cl ass = λr : Count er Rep. { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . r . x: =succ( ! ( r . x) ) r eset = λ_: Uni t . r . x: =1} : Count er RepReset Count er
l et r = { x=r ef 1} i n count er Cl ass r : Count er count er Cl ass = λr : Count er Rep. { get = λ_: Uni t . ! ( r . x) , i nc = λ_: Uni t . x: =succ( ! ( r . x) ) } : Count er RepCount er
How to define r eset Count er Cl ass in terms of count er Cl ass??
r eset Count er Cl ass = λr : Count er Rep. l et super super = count er Cl ass r i n { get = super super . get , i nc = super super . i nc, r eset = λ_: Uni t . r . x: =1} : Count er RepReset Count er
Can we instantiate r eset Count er Cl ass with a different record of instance variables? r eset Count er Cl ass = λr : Count er Rep. l et super super = count er Cl ass r i n { get = super super . get , i nc = super super . i nc, r eset = λ_: Uni t . r . x: =1} : Count er RepReset Count er E.g. BackupCount er Rep = { x: Ref Nat , b: Ref Nat }
Can we instantiate r eset Count er Cl ass with a different record of instance variable?? r eset Count er Cl ass = λr : Count er Rep. l et super super = count er Cl ass r i n { get = super super . get , i nc = super super . i nc, r eset = λ_: Uni t . r . x: =1} : Count er RepReset Count er E.g. BackupCount er Rep = { x: Ref Nat , b: Ref Nat } backupCount er Cl ass = λr : BackupCount er Rep. l et super super = r eset Count er Cl ass r i n { get = super super . get , i nc = super super . i nc, r eset = λ_: Uni t . r . x: =! ( r . b) , backup = λ_: Uni t . r . b: =! ( r . x) } : BackupCount er RepBackupCount er
l et r = { x=r ef 1} i n count er Cl ass r : Count er Class = collection of methods
(type: Count er RepCount er ) An object can be obtained from a Class by instantiating it. Only other use of a Class: extending (= “subtype”) it What is a Class? count er Cl ass r eset Count er Cl ass extend instantiate Count er
set Count er Cl ass = λr : Count er Rep. { get = λ_: Uni t . ! ( r . x) , set = λi : Nat . r . x: =i , i nc = λ_: Uni t . set ( succ( get uni t ) ) } : Count er RepSet Count er Set Count er = { get : Uni t Nat , set : Nat Uni t , i nc: Uni t Uni t } not possible!! get / set come from Set Count er itself!
Recall the f i x
Γ ` t 1 : T1T1 Γ ` f i x t 1 : T1
T1 need not be a function type!! can be a record type!! f f = λm ut r ec: { i seven: Nat Bool , i sodd: Nat Bool } . { i seven = λx: Nat . i f i szer o x t hen t r ue el se m ut r ec. i sodd ( pr ed x) , i sodd = λx: Nat . i f i sZer o x t hen f al se el se m ut r ec. i seven ( pr ed x) } ( f i x f f ) . i seven 7 … f al se
set Count er Cl ass = λr : Count er Rep. { get = λ_: Uni t . ! ( r . x) , set = λi : Nat . r . x: =i , i nc = λ_: Uni t . set ( succ( get uni t ) ) } ) : Count er RepSet Count er Set Count er = { get : Uni t Nat , set : Nat Uni t , i nc: Uni t Uni t } not possible!! get / set come from Set Count er itself!
set Count er Cl ass = λr : Count er Rep. f i x ( λsel f : Set Count er . { get = λ_: Uni t . ! ( r . x) , set = λi : Nat . r . x: =i , i nc = λ_: Uni t . sel f . set ( succ( sel f . get uni t ) ) } ) : Count er RepSet Count er Set Count er = { get : Uni t Nat , set : Nat Uni t , i nc: Uni t Uni t } get / set come from Set Count er itself! newSet Count er = λ_: Uni t . l et r ={ x=r ef 1} i n set Count er Cl ass r
set Count er Cl ass = λr : Count er Rep. f i x ( λsel f : Set Count er . { get = λ_: Uni t . ! ( r . x) , set = λi : Nat . r . x: =i , i nc = λ_: Uni t . sel f . set ( succ( sel f . get uni t ) ) } ) : Count er RepSet Count er newSet Count er = λ_: Uni t . l et r ={ x=r ef 1} i n set Count er Cl ass r
set Count er Cl ass = λr : Count er Rep. f i x ( λsel f : Set Count er . { get = λ_: Uni t . ! ( r . x) , set = λi : Nat . r . x: =i , i nc = λ_: Uni t . sel f . set ( succ( sel f . get uni t ) ) } ) : Count er RepSet Count er newSet Count er = λ_: Uni t . l et r ={ x=r ef 1} i n set Count er Cl ass r
set Count er Cl ass = λr : Count er Rep. f i x ( λsel f : Set Count er . { get = λ_: Uni t . ! ( r . x) , set = λi : Nat . r . x: =i , i nc = λ_: Uni t . sel f . set ( succ( sel f . get uni t ) ) } ) : Count er RepSet Count er Count er Rep Set Count er Set Count er newSet Count er = λ_: Uni t . l et r ={ x=r ef 1} i n set Count er Cl ass r f i x ( set Count er Cl ass r )
set Count er Cl ass = λr : Count er Rep. ( λsel f : Set Count er . { get = λ_: Uni t . ! ( r . x) , set = λi : Nat . r . x: =i , i nc = λ_: Uni t . sel f . set ( succ( sel f . get uni t ) ) } ) : Count er Rep Set Count er Set Count er NOW, methods of a superclass can call methods of a subclass, even though the subclass does not exist when the superclass is being defined!!
set Count er Cl ass = λr : Count er Rep. ( λsel f : Set Count er . { get = λ_: Uni t . ! ( r . x) , set = λi : Nat . r . x: =i , i nc = λ_: Uni t . sel f . set ( succ( sel f . get uni t ) ) } ) : Count er Rep Set Count er Set Count er NOW, methods of a superclass can call methods of a subclass, even though the subclass does not exist when the superclass is being defined!! accCount er Cl ass = λr : AccCount er Rep. λsel f : AccCount er . l et super = set Count er Cl ass r sel f i n { get = super . get , set = λi : Nat . ( r . a: =succ( ! ( r . a) ) ; super . set i ) , i nc = super . i nc, acc = λ_: Uni t . ! ( r . a) } : AccCount er Rep AccCount er AccCount er
accCount er Cl ass = λr : AccCount er Rep. λsel f : AccCount er . l et super = set Count er Cl ass r sel f i n { get = … Nice idea. BUT does NOT work like this!! newAccCount er Cl ass uni t l et r = { x=r ef 1, a=r ef 0} i n f i x ( accCount er Cl ass r ) … < does NO T t er m i nat e! ! ! > Why? Because occurrence of sel f is “unprotected” Unprotected!
accCount er Cl ass = λr : AccCount er Rep. λsel f : AccCount er . l et super = set Count er Cl ass r sel f i n { get = … Nice idea. BUT does NOT work like this!! newAccCount er Cl ass uni t l et r = { x=r ef 1, a=r ef 0} i n f i x ( accCount er Cl ass r ) … < does NO T t er m i nat e! ! ! > Why? Because occurrence of sel f is “unprotected” Unprotected! How to fix this?? 1. protect the sel f by λ-abstraction
Take objects/classes as NEW PRIMITIVES In fact, the language FJ consist only of these primitives. “everything is an object!” Almost as pure as the lambda-calculus (and almost as degenerate as simply typed lambda calculus wo. base types.)
Take objects/classes as NEW PRIMITIVES l et r = { x=r ef 1} i n count er Cl ass r : Count er Class = collection of methods (w.r.t. instance variables) can be extended, or instantiated.
Take objects/classes as NEW PRIMITIVES l et r = { x=r ef 1} i n count er Cl ass r : Count er Class = collection of methods (w.r.t. instance variables) can be extended, or instantiated. must extend another Class Cl ass r eset Count er ext ends Count er { Nat b; r eset Count er ( Nat x, Nat b) { super ( x) , t hi s. b=b; } Nat r eset ( ) { r et ur n new Nat ( 1) ; } } Every class (transitively) extends the class O bj ect O bj ect
Take objects/classes as NEW PRIMITIVES l et r = { x=r ef 1} i n count er Cl ass r : Count er Class = collection of methods (w.r.t. instance variables) can be extended, or instantiated. must extend another Class Cl ass r eset Count er ext ends Count er { Nat b; r eset Count er ( Nat x, Nat b) { super ( x) , t hi s. b=b; } Nat r eset ( ) { r et ur n new Nat ( 1) ; } } constructor new fields new methods all instance variables Every class (transitively) extends the class O bj ect O bj ect
Take objects/classes as NEW PRIMITIVES l et r = { x=r ef 1} i n count er Cl ass r : Count er Class = collection of methods (w.r.t. instance variables) can be extended, or instantiated. must extend another Class Cl ass r eset Count er ext ends Count er { Nat b; r eset Count er ( Nat x, Nat b) { super ( x) , t hi s. b=b; } Nat r eset ( ) { r et ur n new Nat ( 1) ; } } constructor new fields new methods all instance variables Every class (transitively) extends the class O bj ect O bj ect Count er r eset Count er
How do we instantiate a class? new Count er ( t _1, … , t _n) Object Creations are the only values! (like in pure λ) E.g. new A( ) , new B( ) , new A( new B( ) , new C( ) ) , … Object Creation (similar to λ-abstraction) t . m ( t _1, . . , t _n) Method Invocation (similar to function application) x Variables (same as in λ-calculus) t . f Field Access (like in records..) ( sCl ass) t Cast (like subsumption)
FJ Program = collection of Class Declarations plus a Term to be evaluated Cl ass A ext ends O bj ect { A( ) { super ( ) ; } } Cl ass B ext ends O bj ect { B( ) { super ( ) ; } } Cl ass Pai r ext ends O bj ect { O bj ect f st ; O bj ect snd; Pai r ( O bj ect f st , O bj ect snd) { super ( ) ; t hi s. f st =f st ; t hi s. snc=snd; } Pai r set f st ( O bj ect newf st ) { r et ur n new Pai r ( newf st , t hi s. snd) ; } } new Pai r ( new A( ) , new B( ) ) . set f st ( new B( ) )
FJ Program = collection of Class Declarations plus a Term to be evaluated Cl ass A ext ends O bj ect { A( ) { super ( ) ; } } Cl ass B ext ends O bj ect { B( ) { super ( ) ; } } Cl ass Pai r ext ends O bj ect { O bj ect f st ; O bj ect snd; Pai r ( O bj ect f st , O bj ect snd) { super ( ) ; t hi s. f st =f st ; t hi s. snc=snd; } Pai r set f st ( O bj ect newf st ) { r et ur n new Pai r ( newf st , t hi s. snd) ; } } new Pai r ( new A( ) , new B( ) ) . set f st ( new B( ) )
FJ Program = collection of Class Declarations plus a Term to be evaluated Cl ass A ext ends O bj ect { A( ) { super ( ) ; } } Cl ass B ext ends O bj ect { B( ) { super ( ) ; } } Cl ass Pai r ext ends O bj ect { O bj ect f st ; O bj ect snd; Pai r ( O bj ect f st , O bj ect snd) { super ( ) ; t hi s. f st =f st ; t hi s. snc=snd; } Pai r set f st ( O bj ect newf st ) { r et ur n new Pai r ( newf st , t hi s. snd) ; } } new Pai r ( new A( ) , new B( ) ) . set f st ( new B( ) )
Method Invocation: mbody(setfst, Pair) = ( newfst, new Pair(newfst, this.snd) ) (new C(v1,v2)).setfst(u1) [newfstu1, thisnew C(v1,v2)] t0 t0
FJ Program = collection of Class Declarations plus a Term to be evaluated Cl ass A ext ends O bj ect { A( ) { super ( ) ; } } Cl ass B ext ends O bj ect { B( ) { super ( ) ; } } Cl ass Pai r ext ends O bj ect { O bj ect f st ; O bj ect snd; Pai r ( O bj ect f st , O bj ect snd) { super ( ) ; t hi s. f st =f st ; t hi s. snc=snd; } Pai r set f st ( O bj ect newf st ) { r et ur n new Pai r ( newf st , t hi s. snd) ; } } ( ( Pai r ) new Pai r ( new Pai r ( new A( ) , new B( ) ) , new A( ) ) . f st ) . snd
FJ Program = collection of Class Declarations plus a Term to be evaluated Cl ass A ext ends O bj ect { A( ) { super ( ) ; } } Cl ass B ext ends O bj ect { B( ) { super ( ) ; } } Cl ass Pai r ext ends O bj ect { O bj ect f st ; O bj ect snd; Pai r ( O bj ect f st , O bj ect snd) { super ( ) ; t hi s. f st =f st ; t hi s. snc=snd; } Pai r set f st ( O bj ect newf st ) { r et ur n new Pai r ( newf st , t hi s. snd) ; } } ( ( Pai r ) new Pai r ( new Pai r ( new A( ) , new B( ) ) , new A( ) ) . f st ) . snd
Field Selection: f st is declared to contain an O bj ect Thus, the return new Pai r ( new A( ) , new B( ) ) is now an Object!
FJ Program = collection of Class Declarations plus a Term to be evaluated Cl ass A ext ends O bj ect { A( ) { super ( ) ; } } Cl ass B ext ends O bj ect { B( ) { super ( ) ; } } Cl ass Pai r ext ends O bj ect { O bj ect f st ; O bj ect snd; Pai r ( O bj ect f st , O bj ect snd) { super ( ) ; t hi s. f st =f st ; t hi s. snc=snd; } Pai r set f st ( O bj ect newf st ) { r et ur n new Pai r ( newf st , t hi s. snd) ; } } ( ( Pai r ) new Pai r ( new Pai r ( new A( ) , new B( ) ) , new A( ) ) . f st ) . snd
Cast is needed, because mbody( snd, Object) is not defined!!
FJ Program = collection of Class Declarations plus a Term to be evaluated Cl ass A ext ends O bj ect { A( ) { super ( ) ; } } Cl ass B ext ends O bj ect { B( ) { super ( ) ; } } Cl ass Pai r ext ends O bj ect { O bj ect f st ; O bj ect snd; Pai r ( O bj ect f st , O bj ect snd) { super ( ) ; t hi s. f st =f st ; t hi s. snc=snd; } Pai r set f st ( O bj ect newf st ) { r et ur n new Pai r ( newf st , t hi s. snd) ; } } ( ( Pai r ) new Pai r ( new Pai r ( new A( ) , new B( ) ) , new A( ) ) . f st ) . snd
FJ Program = collection of Class Declarations plus a Term to be evaluated Cl ass A ext ends O bj ect { A( ) { super ( ) ; } } Cl ass B ext ends O bj ect { B( ) { super ( ) ; } } Cl ass Pai r ext ends O bj ect { O bj ect f st ; O bj ect snd; Pai r ( O bj ect f st , O bj ect snd) { super ( ) ; t hi s. f st =f st ; t hi s. snc=snd; } Pai r set f st ( O bj ect newf st ) { r et ur n new Pai r ( newf st , t hi s. snd) ; } } ( ( Pai r ) new Pai r ( new Pai r ( new A( ) , new B( ) ) , new A( ) ) . f st ) . snd
Syntactically you canNOT see the type O bj ect
Casts only make sense with run-time type look-up. Today’s LAB:
t oday FJ FJ
l ab
FG J
Programming Assignments To be turned in!