Download presentation
Presentation is loading. Please wait.
1
1 Unifying Object-Oriented Programming with Typed Functional Programming Hongwei Xi Boston University
2
2 Talk Overview Motivation for this work Some difficult issues in designing a type system to support object-oriented programming An approach to implementing objects through the use of guarded recursive datatype constructors
3
3 Motivation Support object-oriented programming in a typed functional programming language Take a CLOS-like approach to object- oriented programming Following Smalltalk, objects are not treated as records in this approach
4
4 Difficulties in Typing Objects All existing approaches to typing objects that we know contain some major deficiencies The programmer needs to program around the deficiencies Run-time type checks are employed to overcome the deficiencies Some deficiencies exist even in a bare minimum core that supports object-oriented programming
5
5 A Problem with Return Types class ObjClass { … virtual copy: ObjClass; … } class StringClass inherits ObjClass { … copy = … … }
6
6 A Problem with Binary Methods class eqClass { virtual equal (other: eqClass): bool; … } class aEqClass inherits eqClass { … } class bEqClass inherits eqClass { … }
7
7 A Puzzling Example class objClass { … virtual copy: objClass; … } class int1Class inherits objClass{ … copy =... ; … } class int2Class inherits int1Class { … }
8
8 Types for Messages We use MSG as a type constructor for constructing types for messages Given a type , the type MSG is for messages that require objects to return values of type after receiving them.
9
9 Message Constructors We can use some syntax to declare message constructors: MSGgetfst: (int) MSG MSGsetfst: int -> (unit) MSG MSGgetsnd: (int) MSG MSGsetsnd: int -> (unit) MSG
10
10 A Type for Objects We can now use the following type for objects: OBJ = {’a}. ’a MSG -> ’a
11
11 Object Constructor for IntPairClass fun newIntPair (x:int, y:int): OBJ = let val xref = ref x val yref = ref y fun dispatch (MSGgetfst) = !xref | dispatch (MSGsetfst x’) = (xref := x’) | dispatch (MSGgetsnd) = !yref | dispatch (MSGsetsnd y’) = (yref := y’) | dispatch msg = raise UnknownMessage in dispatch end
12
12 A Serious Problem As in Smalltalk, there is so far no type- level differentiation between objects For instance, let anIntPair be an object constructed by calling newIntPair. If we send a message MSGfoo to anIntPair, then an exception is to be thrown at run-time. We would really like to have a type system that can stop this at compile-time
13
13 Class Tags We treat classes as tags. A message type is now of the form: MSG(C), where C is a class tag. For instance, MSGgetfst: (int)MSG(IntPairClass) MSGsetfst: int -> (unit)MSG(IntPairClass) The type of an object is of the form: OBJ(C) = {’a}. ’a MSG(C) -> ’a For instance, newIntPair: int int -> OBJ(IntPairClass)
14
14 Parameterized Class Tags There is an immediate need for class tags parameterized over types: MSGgetfst: {’a,’b}. (’a) MSG((’a,’b)PairClass) MSGsetfst: {’a,’b}. ’a -> (unit) MSG((’a,’b)PairClass) MSGgetsnd: {’a,’b}. (’b) MSG((’a,’b)PairClass) MSGsetsnd: {’a,’b}. ’b -> (unit) MSG((’a,’b)PairClass)
15
15 Object Constructor for PairClass fun newPair (x, y) = let val xref = ref x val yref = ref y fun dispatch (MSGgetfst) = !xref | dispatch (MSGsetfst x’) = (xref := x’) | dispatch (MSGgetsnd) = !yref | dispatch (MSGsetsnd y’) = (yref := y’) in dispatch end withtype {’a,’b}. ’a ’b -> OBJ((’a,’b)PairClass)
16
16 Subclasses We define a relation on class tags {’a,’b}. (’a,’b)ColoredPairClass < (’a,’b)PairClass The type of a message constructor is now of the following form: {’a 1,…,’a n,c ( 2 ) MSG(c) For instance, MSGgetfst: {’a,’b,c (unit) MSG(c)
17
17 Contravariant Use of SelfType class EqClass { MSGeq: SelfType -> bool; MSGneq: SelfType -> bool; } MSGeq: {c (bool) MSG(c) MSGneq: {c (bool) MSG(c)
18
18 Covariant Use of SelfType class objClass { … … MSGclone: SelfType … … } MSGclone: {c <= ObjClass}. (OBJ(c)) MSG(c)
19
19 Inheritance We explain how inheritance can be implemented. class Int1Class inherits ObjClass { MSGget1: int; MSGset1: int -> unit; MSGdouble: unit => self(MSGset1(2 self(MSGget1))); } The declaration essentially does the following: Int1Class (unit) MSG(c) MSGdouble: {c <= Int1Class} (unit) MSG(c)
20
20 Super Functions Each class is associated with a “super” function Given a class C, the super function associated with C has the type: {c OBJ(c)
21
21 Examples of Super Functions fun superObj (self) = let fun dispatch (MSGclone) = self | dispatch msg = raise UnknownMessage in dispatch end withtype {c OBJ(c) fun superInt1 (self) = let fun dispatch (MSGdouble) = self(MSGset1(2 self(MSGget1))) | dispatch msg = superObj self msg in dispatch end withtype {c OBJ(c)
22
22 Object Constructor for Int1Class We implement an object constructor for the Int1Class as follows: fun newInt1 (x)= let val xref = ref x fun dispatch (MSGget1) = !xref | dispatch (MSGset1 x’) = (xref := x’) | dispatch (MSGclone) = newInt1 (!xref) | dispatch msg = superInt1 dispatch msg in dispatch end withtype int -> OBJ(Int1Class)
23
23 A Class Declaration class Int2Class inherits Int1Class { MSGget2: int; MSGset2: int -> unit; } The declaration essentially does the following: Int2Class <= Int1Class MSGget2: {c <= Int2Class} (int) MSG(c) MSGset2: {c (unit) MSG(c)
24
24 Super Function and Constructor for Int2Class fun superInt2 (self) = let fun dispatch msg = superInt1 self msg withtype {c OBJ(c) fun newInt2 (x1, x2) = let val x1ref = ref x1 val x2ref = ref x2 fun dispatch (MSGget1) = !x1ref | dispatch (MSGset1 x) = (x1ref := x) | dispatch (MSGget2) = !x2ref | dispatch (MSGset2 x) = (x2ref := x) | dispatch msg = superInt2 dispatch msg in dispatch end withtype int * int -> OBJ(Int2Class)
25
25 Some Interesting Questions Let O2 be an object created by calling newInt2 What happens if we send the message MSGdouble to O2: O2(MSGdouble) ? No method is implemented for MSGdouble in newInt2 No method is implemented for MSGdouble in superInt2 A method lookup finds it through superInt1 What happens if we sent the message MSGclone to O2: O2(MSGclone) ? No method is implemented for MSGclone in newInt2 No method is implemented for MSGclone in superInt2 No method is implemented for MSGclone in superInt1 A method finds it through superObj
26
26 Subtyping Given a class tag C, OBJECT(C) = [c <= C] OBJ(c) E.g., OBJ((OBJECT(eqClass),OBJECT(eqClass))pairClass) is the type for pairs whose both components support equality test
27
27 Type Representation typecon (type) TY = (int) TYint | {’a,’b}. (’a * ’b) TYtup of ’a TY * ’b TY | {’a,’b}. (’a -> ’b) TYfun of ’a TY * ’b TY | {’a}. (’a TY) TYtyp of ’a TY TYint: (int) TY TYtup: {’a,’b}. ’a TY * ’b TY -> (’a * ’b) TY TYfun: {’a,’b}. ’a TY * ’b TY -> (’a -> ’b) TY TYtyp: {’a}. ’a TY -> (’a TY) TY
28
28 An Example: val2string fun val2string pf x = case pf of TYint => int2string x | TYtup (pf1, pf2) => “(” ^ val2string pf1 (fst x) ^ “,” ^ val2string pf2 (snd x) ^ “)” | TYfun _ => “[a function]” | TYtyp _ => “[a type]” withtype {’a}. ’a TY -> ’a -> string
29
29 H.O.A.S. Trees typecon (type) HOAS = {’a}. (’a) HOASlift of ’a | {’a}. (’a) HOASif of bool HOAS * ’a HOAS * ’a HOAS | {’a,’b}. (’a * ’b) HOAStup of ’a HOAS * ’b HOAS | {’a,’b}. (’a -> ’b) HOASlam of ’a HOAS -> ’b HOAS | {’a}. (’a) HOASfix of ’a HOAS -> ’a HOAS HOASlift: {’a}. ’a -> ’a HOAS HOASif: {’a}. bool HOAS * ’a HOAS * ’a HOAS -> ’a HOAS HOAStup: {’a,’b}. ’a HOAS * ’b HOAS -> (’a * ’b) HOAS HOASlam: {’a,’b}. (’a HOAS -> ’b HOAS) -> (’a -> ’b) HOAS HOASfix: {’a}. (’a HOAS -> ’a HOAS) -> ’a HOAS
30
30 Type-Preserving Evaluation fun eval (HOASlift v) = v | eval (HOASif (b, e1, e2)) = if eval (b) then eval (e1) else eval (e2) | eval (HOAStup (e1, e2)) = (eval (e1), eval (e2)) | eval (HOASlam (f)) = fn x => eval (f (HOASlift x)) | eval (HOASfix f) = eval (f (HOASfix f)) withtype {’a}. ’a HOAS -> ’a
31
31 F.O.A.S. trees typecon (type,type) FOAS = | {’a,’g}. (’a,’g) FOASlift of ’a | {’a,’g}. (’a,’a*’g) FOASone | {’a,’b,’g}. (’a,’b*’g) FOASshift of (’a,’g) FOAS | {’a,’b,’g}. (’a -> ’b,’g) FOASlam of (’b,’a*’g) FOAS | … FOASlift: {’a,’g}. ’a -> (’a,’g) FOAS FOASone: {’a,’g}. (’a,’a*’g) FOAS FOASshift: {’a, ’b,’g}. (’a,’g) FOAS -> (’a,’b*’g) FOAS FOASlam: {’a,’b,’g}. (’b,’a * ’g) FOAS -> (’a -> ’b,’g) FOAS …
32
32 Type-Preserving Evaluation fun eval (FOASlift v) env = v | eval FOASone (v, env) = v | eval (FOASshift e) (_, env) = eval e env | eval (FOASlam e) env = fn x => eval e (x, env) | … withtype {’a}. (’a,’g) FOAS -> ’g -> ’a fun evaluate (e) = eval e () withtype {’a}. (’a,unit) FOAS -> ’a
33
33 End of the Talk Thank You! Questions?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.