modules

29
cs776(Prasad) L112Modules 1 Modules value : type : function :: structure : signature : functor

Upload: ifama

Post on 08-Jan-2016

25 views

Category:

Documents


0 download

DESCRIPTION

Modules. value : type : function :: structure : signature : functor. Programming in the small Reliability Correctness ( types ) Robustness ( exceptions ) Efficiency Data Structures and Algorithms ( lists, arrays) Abstraction Data ( patterns ) - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Modules

cs776(Prasad) L112Modules 1

Modules

value : type : function ::

structure : signature : functor

Page 2: Modules

cs776(Prasad) L112Modules 2

SML features • Programming in the

small– Reliability

• Correctness (types)

• Robustness (exceptions)

– Efficiency• Data Structures and

Algorithms (lists, arrays)

– Abstraction• Data (patterns)

• Control (higher-order functions)

Declarative (enhances programmer productivity)

• Programming in the large– 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.

Page 3: Modules

cs776(Prasad) L112Modules 3

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)

Page 4: Modules

cs776(Prasad) L112Modules 4

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

Page 5: Modules

cs776(Prasad) L112Modules 5

structurestructure QueueImpl = structstruct datatype 'a t = Q of ('a list * 'a list); exception E;

val empty = Q([],[]); fun norm (Q([],ts)) = Q(rev ts, []) | norm q = q; fun enq(Q(hs,ts), x) = norm(Q(hs, x::ts)); fun null(Q([],[])) = true | null _ = false; fun hd(Q(x::_,_)) = x | hd(Q([],_)) = raise E; fun deq(Q(x::hs,ts)) = norm(Q(hs,ts)) | deq(Q([],_)) = raise E; endend;

Page 6: Modules

cs776(Prasad) L112Modules 6

structurestructure QueueImpl : sigsig 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;end;

Page 7: Modules

cs776(Prasad) L112Modules 7

Information Hiding Concerns

• The implementation details of QueueImpl are exported. – Client code can use pattern matching to

manipulate queues.• Client code can break if the implementation of QueueImpl is changed.

– Client code can ignore the FIFO discipline.• Semantics of queue (invariants) can be violated.

• Possible Solution : Restrict the view

Page 8: Modules

cs776(Prasad) L112Modules 8

Transparent Signature Constraints

signaturesignature Qtip = sigsig 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;end;

structure structure Queue : Qtip = QueueImpl;Queue : Qtip = QueueImpl;

Page 9: Modules

cs776(Prasad) L112Modules 9

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

- Queue.norm; (* error *)

- Queue.hd; val it = fn : 'a QueueImpl.t -> 'a

- Queue.Q; (* error *)

- Queue.empty = QueueImpl.Q ([],[]);- open QueueImpl;- norm(Queue.enq(Queue.empty, “a”)); val it = Q (["a"],[]) : string t

Page 10: Modules

cs776(Prasad) L112Modules 10

Opaque Signature Constraints

structure structure Queue :> Qtip = QueueImpl;;

• This enforces data abstraction.– Only operations that are explicitly defined on Queue can be invoked on Queue-values.

QueueImpl.norm(Queue.enq(Queue.empty,“a”)); (* error *)

– Equality tests (based on the representation) are banned.

Queue.empty = QueueImpl.Q ([],[])); (* error *)

• To allow equality tests, use eqtype ’a t instead of type ’a t.

(Cf. Ada’s Limited Private Types and Private Types)

Page 11: Modules

cs776(Prasad) L112Modules 11

signature SIG = sig val i : int; type t; val x : t val f:t*t -> bool end;

structure STRUC = struct val i = 3; type t = int; val x = 4; fun f(a,b) = (a=b) end;

open STRUC;

f(x,x);

f(i,x); (*val it = false : bool*)

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.)

Page 12: Modules

cs776(Prasad) L112Modules 12

signature SIG = sig val i : int; type t; val x : t val f:t*t -> bool end;

structure STRUC = struct val i = 3; type t = int; val x = 4; fun f(a,b) = (a=b) end;

signature SIG’ = SIG where type t = int;structure STRUC’:> SIG’

= STRUC;open STRUC’;

f(i,x);

(* val it = false : bool*)

• Type t being int is visible because where-clause explicitly exports it.

Page 13: Modules

cs776(Prasad) L112Modules 13

Signature Matching

structure strId : sigExp = strExp ; (* 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.

Page 14: Modules

cs776(Prasad) L112Modules 14

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

Page 15: Modules

cs776(Prasad) L112Modules 15

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

Page 16: Modules

cs776(Prasad) L112Modules 16

Equivalent: QUEUE_AS_LIST and QUEUE_AS_LIST0

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_LIST0 = QUEUE where type

'a queue = 'a list

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 listend

Page 17: Modules

cs776(Prasad) L112Modules 17

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

Page 18: Modules

cs776(Prasad) L112Modules 18

RBT_DT matches RBT

signature RBT_DT = sig datatype 'a rbt = Empty | Red of 'a rbt * 'a * 'a rbt | Black of 'a rbt * 'a * 'a rbt end

signature RBT = sig type 'a rbt val Empty : 'a rbt val Red : 'a rbt * 'a * 'a rbt -> 'a rbt end

Page 19: Modules

cs776(Prasad) L112Modules 19

(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.

Page 20: Modules

cs776(Prasad) L112Modules 20

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 componentsinterchangeability of 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.

Page 21: Modules

cs776(Prasad) L112Modules 21

Functors

• A functorfunctor 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.

Page 22: Modules

cs776(Prasad) L112Modules 22

Example

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

functor MkOrdSet(Ord:Order) = struct exception EmptySetEX; 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 EmptySetEX

else foldr (fn (x,r) => if (Ord.le r x) then r else x) (hd s) (tl s);

end;

Page 23: Modules

cs776(Prasad) L112Modules 23

structure OrdInt: Order = struct type et = int;

fun le (x:et) y = x <= yend;

structure intset = MkOrdSet(OrdInt);

open intset; (min empty); (* uncaught exception *) val s1 = (insert empty 5);

val s2 = (insert s1 3); (* val s2 = SET [3,5] : set *) (min (insert s2 8)); (* val it = 3 : OrdInt.et *)

Page 24: Modules

cs776(Prasad) L112Modules 24

Example Functor (Component Reuse) signature ORDER = sig type t; val compare: t*t -> bool end;structure StringOrder: ORDER = struct type t = string; val compare = String.compare end;

...

structure StringDict = Dictionary (StringOrder);

(* structure StringDict : sig type key = StringOrder.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 *)

Page 25: Modules

cs776(Prasad) L112Modules 25

functor Dictionary (Key: ORDER) = struct type key = Key.t; abstype 'a t = Lf | B of key *'a*'a t *'a t with

exception E of key; val empty = Lf; fun lookup (B(a,x,t1,t2), b) = (case Key.compare(a,b) of GREATER => lookup(t1, b) | EQUAL => x | LESS => lookup(t2, b)) | lookup (Lf, b) = raise E b; fun update (Lf, b, y) = B(b, y, Lf, Lf) | update (B(a,x,t1,t2), b, y) = (case Key.compare(a,b) of GREATER => B(a, x, update(t1,b,y), t2)

| EQUAL => B(a, y, t1, t2) | LESS => B(a, x,t1,update(t2,b,y)));

end end;

Page 26: Modules

cs776(Prasad) L112Modules 26

(cont’d)

infix |< ;

fun (d |< (k,x)) =

StringDict.update(d,k,x);

val dict = StringDict.empty

|< (“abc”, 2) |< (“nbc”, 11)

|< (“dsc”, 53) |< (“tlc”,54);

(* val dict = - : int StringDict.t *)

StringDict.lookup(dict, “dsc”);

(* val it = 53 : int *)

StringDict.lookup(dict, “cnn”);

(* uncaught exception E *)

Page 27: Modules

cs776(Prasad) L112Modules 27

signature INT = sig val i: int end; signature REAL = 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);

Multi-argument Functor

Page 28: Modules

cs776(Prasad) L112Modules 28

Sharing Constraints (for combining / integrating modules)

To express equality constraints among types names.• Type sharing

sharing type <type> = … = <type>

• Structure sharingsharing <structure> = … = < structure>

Shorthand for sharing of identically named types within the equated structures.

Page 29: Modules

cs776(Prasad) L112Modules 29

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 * bt; val leaf : elt -> bt; val build : elt * bt * bt -> bt; val lookup : elt * bt -> bool end;