220 likes | 357 Views
Guarded Recursive Datatype Constructors. Hongwei Xi and Chiyan Chen and Gang Chen Boston University. Talk Overview. Examples of guarded recursive (g.r.) datatype constructors Issues on type-checking in the presence of g.r. datatype constructors Applications of g.r. datatype constructors.
E N D
Guarded Recursive Datatype Constructors Hongwei Xi and Chiyan Chen and Gang Chen Boston University
Talk Overview • Examples of guarded recursive (g.r.) datatype constructors • Issues on type-checking in the presence of g.r. datatype constructors • Applications of g.r. datatype constructors
Type Representation (I) The following syntax declares a guarded recursive datatype constructor TY of the kind type -> type. typecon(type) TY = (* TY: type -> type *)| (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 The value constructors associated with TY are assigned the following types: TYint: (int) TY (int TY) TYtup: {’a,’b}. ’a TY * ’b TY -> (’a * ’b) TY (a. b. a TY * b TY -> (a* b) TY) TYfun: {’a,’b}. ’a TY * ’b TY -> (’a -> ’b) TY (a. b. a TY * b TY -> (a->b) TY) TYtyp: {’a}. ’a TY -> (’a TY) TY (a. a TY -> (a TY) TY) Given a typet, the representation oft has the type (t) TY
Type Representation (II) • For instance, • The type int is represented as TYint, which is of the type (int)TY. • The type int -> intis represented as TYfun (TYint, TYint),which is of the type(int -> int) TY. • The typeint * int -> intis represented asTYfun (TYtup (TYint, TYint), TYint),which is of the type (int * int -> int)TY.
Type Representation (III) fun val2string (TYint) = fn x => int2string x| val2string (TYtup (pf1, pf2)) = fn x => “(“ ^ val2string pf1 (fst x) ^ “,” ^ val2string pf2 (snd x) ^ “)”| val2string (TYfun _) = fn _ => “[a function value]”| val2string (TYtyp _) = fn _ => “[a type value]” withtype {‘a}. ‘a TY -> ‘a -> string Given a term pf representing type t and a value v of type t, (val2sting pf v) returns a string representation of v.
A Special Case: Datatypes in ML The datatype constructors in ML are a special case of g.r. datatype constructors. For instance, datatype ‘a list = nil | cons of ‘a * ‘a list corresponds to: typecon (type) list = {‘a}. (‘a) nil| {‘a}. (‘a) cons of ‘a * ‘a list
Another Special Case: Nested Datatypes The nested datatype constructors are also a special case of g.r. datatype constructors. For instance, datatype ‘a raList =Nil | Even of (‘a * ‘a) raList | Odd of ‘a * (‘a * ‘a) raList correponds to typecon (type) raList = {‘a}. (‘a) Nil| {‘a}. (‘a) Even of (‘a * ‘a) raList | {‘a}. (‘a) Odd of ‘a * (‘a * ‘a) raList
Define G.R. Datatype Constructors types t ::= a | 1 | t1*t2| t1->t2 | (t1,...,tn) T | a.t type variable contextsD ::= | D, a | D, t1 t2 As an example, TY is formally defined as follows:mt: type -> type.la.{a int}.1 + {a1,b1, a a1* b1}. (a1) t *(b1) t + {a1, b1, a a1 -> b1}. (a1) t *(b1) t + {a1, a (a1)t}. (a1) t So we call TY a guarded recursive datatype constructor.
Type Constraints • A type constraint is of the form: D |= t t • We say Qis a solution to D if Q(t1) =a Q(t2) for each guard t1 t2 in D, where =ais the usual syntactic equality modulo a-conversion. • D |= t t holds ifQ(t) =a Q(t)for all solutions Q to D. • The relationD |= t t is decidable.
Typing Patterns: D0|- p t => (D; G), whereGis a term variable context defined as follows: G::= | G, x : t For instance, the following rule is for handling constructors: c::a1...am. t -> (t1,...,tn)TD0,a1,...,am ,t1 t1 ,..., tn tn|- p t => (D; G)------------------------------------------------D0|- c(p) (t1 ,..., tn )T => (a1,...,am ,t1 t1 ,..., tn tn ,D; G)
Typing Pattern Match Clauses (I) • The following rule is for typing pattern match clauses:D0|- p t1 => (D; G) D0, D; G0,G |- e: t2 D0;G0|- p => e: t1 => t2
Typing Pattern Match Clauses (II) Let us see an example: TYint => (fn x => int2string x) ‘a TY => (‘a -> string) TYint ‘a TY => (int ‘a; ) int ‘a; |- fn x => int2string x : ‘a -> string
Higher-Order Abstract Syntax Trees (I) datatype HOAS = HOASlam of HOAS -> HOAS| HOASapp of HOAS * HOAS For instance, the lambda-term lxly.x(y) is represented as HOASlam(fn x => HOASlam (fn y => HOASapp (x, y))) typecon (type) HOAS = {’a,’b}. (’a -> ’b) HOASlam of ’a HOAS -> ’b HOAS| {’a,’b}. (’b) HOASapp of (’a -> ‘b) HOAS * ’b HOAS HOASlam: {’a,’b}. (’a HOAS -> ’b HOAS) -> (’a -> ’b) HOAS HOASapp: {’a,’b}. (’a -> ‘b) HOAS * ’a HOAS -> ‘b HOAS (t)HOASis the type for h.o.a.s. trees representing expressions whose values have the typet. Note g.r. datatype constructors cannot in general be defined inductively over types.
Higher-Order Abstract Syntax Trees (II) fun hnf (t as HOASlam _) = t| hnf (HOASapp (t1, t2)) = case hnf (t1) of HOASlam f => hnf (f t2) | t1’ => HOASapp (t1’, t2) withtype {‘a}. ‘a HOAS -> ‘a HOAS The function hnf computes the head normal form of a given lambda-expression.
Implementing Programming Objects • Let MSG be an extensible g.r. datatype constructor of the kind type -> type. • Intuitively, (t) MSG is the type for a message that requires its receiver to return a value of type t. • We use the following type Obj for objects:{‘a}. (‘a) MSG -> ‘aThat is, an object is a function that returns a value of type t when applied to a message of the type (t) MSG.
Integer Pair Objects • We first assume that the following value constructors have been defined through some syntax:MSGgetfst: (int) MSG MSGgetsnd: (int) MSGMSGsetfst: int ->(unit) MSG MSGsetsnd: int -> (unit) MSG fun newIntPair (x: int, y: int): Obj = let val xref = ref x and yref = ref y fun dispatch (MSGgetfst) = !x | dispatch (MSGgetsnd) = !y | dispatch (MSGsetfst x’) = xref := x’ | dispatch (MSGsetsnd y’) = yref := y’ | dispatch _ = raise UnknownMessage in dispatch end
The Type Obj Is Unsatisfactory • There is an obvious problem with the type Obj = {‘a} (‘a) MSG -> ‘a for objects: it is impossible to use types to differentiate objects. • Assume anIntPair is an integer pair object and MSGfoo is some message; thenanIntPair (MSGfoo)is well-typed and its execution results in a run-time UnknownMessage exception to be raised.
But We Can Do Much Better! • Please find in the paper an approachto implementing programming objects based on the above idea.
More Applications • Implementing type classes • Implementing meta-programming • Implementing typed code transformation • Implementing …
Some Related Works • Intensional polymorphism (Harper, Morrisett, Crary, Weirich; Shao, Trifinov, Saha, et al) • Generic polymorphism (Dubois, Rouaix, Weis) • Qualified Types (Mark Jones) • Dependent ML (Xi and Pfenning)
End of the Talk • Thank you! Questions?