Modules value type function structure signature functor cs

  • Slides: 29
Download presentation
Modules value type : function : : structure : signature : functor cs 7120(Prasad)

Modules value type : function : : structure : signature : functor cs 7120(Prasad) : L 8 -MOD 1

SML features • Programming in the small • Programming in the large – Reliability

SML features • Programming in the small • Programming in the large – Reliability • Correctness (types) • Robustness (exceptions) – Efficiency • Data Structures and Algorithms (lists, arrays) – Abstraction • Data (patterns) • Control (higher-order functions) Declarative (enhances programmer productivity) cs 7120(Prasad) L 8 -MOD – Cluster related definitions; hierarchical organization of programs (structures) – Encapsulation (localization) of implementation details, for clarity and modifiability (abstype, signatures) – Reusability and interchangeability of parts (functors). • Separate compilation. • Standard libraries. 2

Customization of Modules • Controlling visibility of names (Managing environments) – To avoid potential

Customization of Modules • Controlling visibility of names (Managing environments) – To avoid potential name conflicts. • Multiple implementations of an ADT (e. g, Table). • Similar operations on different ADTs (e. g. , delete on Set, List, Table, etc). • Programmer choice of names, to conform to domain vocabulary. – To encapsulate representation details. • To enable transparent changes to the impl. • To preserve data integrity (invariants) • Instantiation (Specializing w. r. t. types) cs 7120(Prasad) L 8 -MOD 3

SML Constructs • Structure – Collection of definitions • E. g. , Ada/Java packages,

SML Constructs • Structure – Collection of definitions • E. g. , Ada/Java packages, C++/Java classes, etc • Signature – Type declarations of the names • E. g. , Ada package specification, Java interfaces, etc • Functor – Maps a structure to another structure – Parameterized structures • E. g. , Ada generic units, C++ templates, Java functions with interface/class parameters, etc cs 7120(Prasad) L 8 -MOD 4

structure Queue. Impl = struct datatype 'a t = Q of ('a list *

structure Queue. Impl = struct datatype 'a t = Q of ('a list * 'a list); exception E; val fun | fun | end; end cs 7120(Prasad) empty = Q([], []); norm (Q([], ts)) = Q(rev ts, []) norm q = q; enq(Q(hs, ts), x) = norm(Q(hs, x: : ts)); null(Q([], [])) = true null _ = false; hd(Q(x: : _, _)) = x hd(Q([], _)) = raise E; deq(Q(x: : hs, ts)) = norm(Q(hs, ts)) deq(Q([], _)) = raise E; L 8 -MOD 5

structure Queue. Impl : sig datatype 'a t = Q of 'a list *

structure Queue. Impl : sig datatype 'a t = Q of 'a list * 'a list exception E val deq : 'a t -> 'a t val empty : 'a t val enq : 'a t * 'a -> 'a t val hd : 'a t -> 'a val norm : 'a t -> 'a t val null : 'a t -> bool end; cs 7120(Prasad) L 8 -MOD 6

Information Hiding Concerns • The implementation details of Queue. Impl are exported. – Client

Information Hiding Concerns • The implementation details of Queue. Impl are exported. – Client code can use pattern matching to manipulate queues. • Client code can break if the implementation of Queue. Impl is changed. – Client code can ignore the FIFO discipline. • Semantics of queue (invariants) can be violated. • Possible Solution : Restrict the view cs 7120(Prasad) L 8 -MOD 7

Transparent Signature Constraints signature Qtip = sig type ’a t val deq : 'a

Transparent Signature Constraints signature Qtip = sig type ’a t val deq : 'a t -> 'a t val empty : 'a t val enq : 'a t * 'a -> 'a t val hd : 'a t -> 'a val null : 'a t -> bool end; structure Queue : Qtip = Queue. Impl; cs 7120(Prasad) L 8 -MOD 8

- Queue. Impl. norm; val it = fn : 'a Queue. Impl. t ->

- Queue. Impl. norm; val it = fn : 'a Queue. Impl. t -> 'a Queue. Impl. t - Queue. norm; - Queue. hd; (* error *) val it = fn : 'a Queue. Impl. t -> 'a - Queue. Q; (* error *) Queue. empty = Queue. Impl. Q ([], []); open Queue. Impl; norm(Queue. enq(Queue. empty, “a”)); val it = Q (["a"], []) : string t cs 7120(Prasad) L 8 -MOD 9

Opaque Signature Constraints structure Queue : > Qtip = Queue. Impl; • This enforces

Opaque Signature Constraints structure Queue : > Qtip = Queue. Impl; • This enforces data abstraction. – Only operations that are explicitly defined on Queue can be invoked on Queue-values. Queue. Impl. norm(Queue. enq(Queue. empty, “a”)); (* error *) – Equality tests (based on the representation) are banned. Queue. empty = Queue. Impl. Q ([], [])); (* error *) • To allow equality tests, use eqtype ’a t instead of type ’a t. (Cf. Ada’s Limited Private Types and Private Types) cs 7120(Prasad) L 8 -MOD 10

signature SIG = sig val i : int; type t; val x : t

signature SIG = sig val i : int; type t; val x : t val f: t*t -> bool end; open STRUC; f(x, x); f(i, x); (*val it = false : bool*) structure STRUC = struct val i = 3; type t = int; val x = 4; fun f(a, b) = (a=b) end; cs 7120(Prasad) structure STRUC’: > SIG = STRUC; open STRUC’; f(i, x); (* type error *) • Type t created using opaque signatures is regarded as distinct from any other type (including int and other type t created from the same structure. ) L 8 -MOD 11

signature SIG = sig val i : int; type t; val x : t

signature SIG = sig val i : int; type t; val x : t val f: t*t -> bool end; signature SIG’ = SIG where type t = int; structure STRUC’: > SIG’ = STRUC; open STRUC’; f(i, x); structure STRUC = struct val i = 3; type t = int; val x = 4; fun f(a, b) = (a=b) end; cs 7120(Prasad) (* val it = false : bool*) • Type t being int is visible because whereclause explicitly exports it. L 8 -MOD 12

Signature Matching structure str. Id : sig. Exp = str. Exp ; (* target

Signature Matching structure str. Id : sig. Exp = str. Exp ; (* target candidate *) Target signature expresses a set of constraints that the candidate structure must satisfy. Informally, the candidate’s signature may have more components than are required by the target, may have more definitions of types than are required, and may have value components with more general types. cs 7120(Prasad) L 8 -MOD 13

QUEUE_WITH_EMPTY matches QUEUE signature QUEUE = sig type 'a queue exception Empty val empty

QUEUE_WITH_EMPTY matches QUEUE signature QUEUE = sig type 'a queue exception Empty val empty : 'a queue val insert : 'a * 'a queue -> 'a queue val remove : 'a queue -> 'a * 'a queue end signature QUEUE_WITH_EMPTY = sig include QUEUE val is_empty : 'a queue -> bool end cs 7120(Prasad) L 8 -MOD 14

QUEUE_AS_LISTS matches QUEUE signature QUEUE = sig type 'a queue exception Empty val empty

QUEUE_AS_LISTS matches QUEUE signature QUEUE = sig type 'a queue exception Empty val empty : 'a queue val insert : 'a * 'a queue -> 'a queue val remove : 'a queue -> 'a * 'a queue end signature QUEUE_AS_LISTS = QUEUE where type 'a queue = 'a list * 'a list cs 7120(Prasad) L 8 -MOD 15

Equivalent: QUEUE_AS_LIST and QUEUE_AS_LIST 0 signature QUEUE = sig type 'a queue exception Empty

Equivalent: QUEUE_AS_LIST and QUEUE_AS_LIST 0 signature QUEUE = sig type 'a queue exception Empty val empty : 'a queue val insert : 'a * 'a queue -> 'a queue val remove : 'a queue -> 'a * 'a queue end signature QUEUE_AS_LIST 0 = QUEUE where type 'a queue = 'a list cs 7120(Prasad) signature QUEUE_AS_LIST = sig type 'a queue = 'a list exception Empty val empty : 'a list val insert : 'a * 'a list -> 'a list val remove : 'a list -> 'a * 'a list end L 8 -MOD 16

MERGEABLE_QUEUE matches MERGEABLE_INT_QUEUE signature MERGEABLE_QUEUE = sig include QUEUE val merge : 'a queue

MERGEABLE_QUEUE matches MERGEABLE_INT_QUEUE signature MERGEABLE_QUEUE = sig include QUEUE val merge : 'a queue * 'a queue -> 'a queue end signature MERGEABLE_INT_QUEUE = sig include QUEUE val merge : int queue * int queue -> int queue end cs 7120(Prasad) L 8 -MOD 17

RBT_DT matches RBT signature RBT_DT = sig datatype 'a rbt = Empty | Red

RBT_DT matches RBT signature RBT_DT = sig datatype 'a rbt = Empty | Red of 'a rbt * 'a rbt | Black of 'a rbt * 'a rbt end signature RBT = sig type 'a rbt val Empty : 'a rbt val Red : 'a rbt * 'a rbt -> 'a rbt end cs 7120(Prasad) L 8 -MOD 18

(cont’d) • Every type specification (resp. datatype definition) in the target must have a

(cont’d) • Every type specification (resp. datatype definition) in the target must have a matching (resp. equivalent) type specification (resp. datatype definition) in the candidate. • Every exception specification in the target must have an equivalent exception specification in the candidate. • Every value specification in the target must be matched by a value specification in the candidate with at least as general a type. cs 7120(Prasad) L 8 -MOD 19

Relationship between Structures and Signatures • In ML, a signature may serve as an

Relationship between Structures and Signatures • In ML, a signature may serve as an interface for many different structures, and that a structure may implement many different signatures. (interchangeability of components) components • ML, C++, Java† : many-to-many • Modula-2 : one-to-one • Ada-95 : many-to-one. • Every structure has a principal signature, with the property that all other signatures for that structure are more restrictive than the principal signature. cs 7120(Prasad) L 8 -MOD 20

Functors • A functor maps structures to structure. – A functor can be viewed

Functors • A functor maps structures to structure. – A functor can be viewed as a reusable unit that contains well-defined “sockets for plug-ins”. – Parameterized/Generic modules. – Useful in “client-server paradigm” applications exploiting interchangeability of parts with common interface. • Developing floating point libraries that work with different precision implementations. • Building common test harness to verify various implementations of an abstract data type. cs 7120(Prasad) L 8 -MOD 21

Example signature Order = sig eqtype et ; val le : et -> bool

Example signature Order = sig eqtype et ; val le : et -> bool end; functor Mk. Ord. Set(Ord: Order) = struct exception Empty. Set. EX; datatype set = SET of (Ord. et list) val empty = SET nil fun insert (SET s) n = SET (n: : s) fun member (SET s) n = (List. exists (fn x => (x = n)) s) fun min (SET s) = if (null(s)) then raise Empty. Set. EX else foldr (fn (x, r) => if (Ord. le r x) then r else x) (hd s) (tl s); end; cs 7120(Prasad) L 8 -MOD 22

structure Ord. Int: Order = struct type et = int; fun le (x: et)

structure Ord. Int: Order = struct type et = int; fun le (x: et) y = x <= y end; structure intset = Mk. Ord. Set(Ord. Int); open (min val intset; empty); (* uncaught exception *) s 1 = (insert empty 5); s 2 = (insert s 1 3); (* val s 2 = SET [3, 5] : set *) (min (insert s 2 8)); (* val it = 3 : Ord. Int. et *) cs 7120(Prasad) L 8 -MOD 23

Example Functor (Component Reuse) signature ORDER = sig type t; val compare: t*t ->

Example Functor (Component Reuse) signature ORDER = sig type t; val compare: t*t -> bool end; structure String. Order: ORDER = struct type t = string; val compare = String. compare end; . . . structure String. Dict = Dictionary (String. Order); (* structure String. Dict : sig type key = String. Order. t type 'a t exception E of key val empty : 'a t val lookup : 'a t * Key. t -> 'a val update : 'a t * key * 'a -> 'a t end *) cs 7120(Prasad) L 8 -MOD 24

functor Dictionary (Key: ORDER) = struct type key = Key. t; abstype 'a t

functor Dictionary (Key: ORDER) = struct type key = Key. t; abstype 'a t = Lf | B of key *'a*'a t with exception E of key; val empty = Lf; fun lookup (B(a, x, t 1, t 2), b) = (case Key. compare(a, b) of GREATER => lookup(t 1, b) | EQUAL => x | LESS => lookup(t 2, b)) | lookup (Lf, b) = raise E b; fun update (Lf, b, y) = B(b, y, Lf) | update (B(a, x, t 1, t 2), b, y) = (case Key. compare(a, b) of GREATER => B(a, x, update(t 1, b, y), t 2) | EQUAL => B(a, y, t 1, t 2) | LESS => B(a, x, t 1, update(t 2, b, y))); end; cs 7120(Prasad) L 8 -MOD 25

(cont’d) infix |< ; fun (d |< (k, x)) = String. Dict. update(d, k,

(cont’d) infix |< ; fun (d |< (k, x)) = String. Dict. update(d, k, x); val dict = String. Dict. empty |< (“abc”, 2) |< (“nbc”, 11) |< (“dsc”, 53) |< (“tlc”, 54); (* val dict = - : int String. Dict. t *) String. Dict. lookup(dict, “dsc”); (* val it = 53 : int *) String. Dict. lookup(dict, “cnn”); (* uncaught exception E *) cs 7120(Prasad) L 8 -MOD 26

Multi-argument Functor signature INT signature REAL = sig val i: int end; = sig

Multi-argument Functor signature INT signature REAL = sig val i: int end; = sig val r: real end; functor Foo(structure I: INT and R: REAL; val x : int) = struct end; structure Int = struct val i = 0 end; structure Real= struct val r = 0. 0 end; structure Bar = Foo(structure I = Int and R = Real; val x = 2); cs 7120(Prasad) L 8 -MOD 27

Sharing Constraints (for combining / integrating modules) To express equality constraints among types names.

Sharing Constraints (for combining / integrating modules) To express equality constraints among types names. • Type sharing type <type> = … = <type> • Structure sharing <structure> = … = < structure> Shorthand for sharing of identically named types within the equated structures. cs 7120(Prasad) L 8 -MOD 28

signature ELEMENT = sig type element; val similar : element * element -> bool;

signature ELEMENT = sig type element; val similar : element * element -> bool; end; signature BTREE = sig structure Element: ELEMENT; eqtype elt; sharing type elt = Element. element; datatype bt = Empty | Node of elt * bt; val leaf : elt -> bt; val build : elt * bt -> bt; val lookup : elt * bt -> bool end; cs 7120(Prasad) L 8 -MOD 29