1 / 33

Data Abstraction

Data Abstraction. COS 441 Princeton University Fall 2004. Existential Types. Powerful mechanism for providing data-abstraction Useful for Lists of Heterogeneous Values Typed Closure Conversion Encoding Modules . Heterogeneous Lists Revisited. Consider a heterogonous list of the form

bena
Télécharger la présentation

Data Abstraction

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Data Abstraction COS 441 Princeton University Fall 2004

  2. Existential Types Powerful mechanism for providing data-abstraction Useful for Lists of Heterogeneous Values Typed Closure Conversion Encoding Modules

  3. Heterogeneous Lists Revisited Consider a heterogonous list of the form val x : ?? list = [1, true, “hello world”] : how can we implement a generic print function? val printList : ?? list ! unit

  4. Tagged List Simple answer is to use tagged datatype datatype tagged = I of int | B of bool | S of string val x = [I 1,B true, S “hello world”] fun tagged2s (I i) = Int.toString i | tagged2s (B b) = Bool.toString b | tagged2s (S s) = s fun printList l = …

  5. Problems With Tagged Approach We must know the type of every value we might want to tag. If a user creates a new type, they have to modify the tagged2s function as well as the tagged datatype Not a modular approach

  6. A More Modular Approach Create a list of “objects” which consist of a value and a function to convert it into a string type obj = ?? val x : obj list = [(1,Int.toString), (true,Bool.toString), (s,(fn x => x))] fun obj2s (x,f) = f x

  7. Typing Problems It doesn’t type check in SML We can get a similar effect with HOF type obj = unit ! string val x : obj list = [(fn () => Int.toString 1), (fn () => Bool.toString true), (fn () => s)] fun obj2s f = f ()

  8. Extending the Type System The type obj should capture the pattern obj = (* (! string)) for some arbitrary  9 t(t* (t! string)) Provides a modular solution that avoids a fixed non-modular tagging scheme.

  9. Closure Conversion Remember functions represented in runtime as a pair “environment” and function body. Consider type obj = unit ! string fun IntObj i = (fn () => Int.toString i) let val obj = IntObj 10 in obj () end

  10. Closure Representation Can represent environments as tuples fun IntObj (_,i) = (i,fn (i,()) => Int.toString i) let val (fenv,f) = IntObj (glbl_env,10) in f (fenv,()) end Size and type of tuple depends on number of free vars. in body of function

  11. Typed Closure Conversion Closure conversion done by the compiler user doesn’t care what goes on or how the environment is represented! However, useful to be able check the output of the compiler for debugging and security reasons Also notice that closures are just like our “object” type i.e. a piece of private data stored with something that knows how to manipulate it We can us existential to make the result of the compiler type checkable!

  12. Existential Types

  13. Example: pack type obj = 9 t((t * (t ! string)) pack int with (1,Int.toString) as 9 t((t * (t ! string)) Note: type of (1,Int.toString) = (int * (int ! string))  [t int](t * (t ! string)

  14. Example: open fun obj2s (obj:9 t((t * (t ! string))) = open obj as t with x:(t * (t ! string)) in let val (v:t,v2s:(t! string)) = x in v2s v end

  15. Static Semantics

  16. Dynamic Semantics

  17. Modules and Existentials Can be encode with the type 9q((q * ((int * q) ! q) * (q ! (int * q))))

  18. Representation Independence A simple reference implementation of a queue pack int list with (nil,fun insert …,fun remove …) as 9q((q * ((int * q) ! q) * (q ! (int * q))))

  19. Client of a Module open QL as q with <e,i,r> : (q * ((int * q) ! q) * (q ! (int * q))) in … end

  20. Representation Independence • Imagine we have to “equivalent” implementations of a module • The behave externally the same way but may use different internal representations of data structures • A client should work correctly assuming the implementations are equivalent

  21. Example Consider the slightly more efficient representation of a queue

  22. Formal Definition Let q be (q * ((int * q) ! q) * (q ! (int * q))) Let q be 9q(q) Let the expression that represents the module QL be vQL:q and the expression that represents the module QFB be vQFB:q We wish to show for any client code ec :c open vQL as q with x:q in ec :c behaves equivalently to open vQFB as q with x:q in ec:c

  23. What Definition of Equivalent? We can use the framework of parametricity to define equivalence at some type

  24. Definition of Value Equivalence Define a notion of equivalence of closed values indexed by type

  25. Definition of Value Equivalence Interesting case is definition of “all”

  26. Definition of Value Equivalence Definition of “some” Some simulation relation

  27. `ec:8t(t!c) `c ok `openeiusingec:c Alternative View Key observation that relates data-abstraction and parametricity

  28. Client Equivalence So to because the client is just a polymorphic function and from the parametricity theorem we can conclude if we know v1 and v2 are equivalent existential packages

  29. Equivalence of Modules Definition of “some” To show modules equivalent choose some R and show implementations are equivalent under R Some simulation relation

  30. vQLvalvQFB : q First we must choose some R Let R be Then assuming that v1valv2 : q iff (v1,v2) 2R show 1. QL.empty val QFB.empty : q 2. QL.insert val QFB.insert : (int * q) ! q 3. QL.remove val QFB.remove: q ! (int * q)

  31. Note About Proofs Proofs are tedious Have you ever seen an interesting proof yet?  Formalisms we present in class are to make you aware that precise formal definitions exist for abstraction and modularity

  32. What Do I Need To Know? I had to read through Harper’s notes several times carefully to understand them! Therefore I won’t assign a homework/test question about formal notions of parametricity/data abstraction! However, it is educational to understand the high-level structure of the definitions and how they relate to one another

  33. Summary Existential type allow you to enforce data-abstraction Data-abstraction exists because “client” code is polymorphic with respect to the actual type Can encode modules, closures, and objects with existential types in a type safe way

More Related