Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
ML
modules
Daniel JacksonM
IT Lab for Computer Science
6898: Advanced Topics in Software DesignM
arch 20, 2002
2
topics for today
elements of M
L module language
›structs: modules, export types and values
›signatures: types for modules
›functors: functions from m
odules to modules
signature ascription›controlling client’s view of a m
odule
functorization›m
aking dependences explicit
3
set implem
entation def and use
module SetIm
pl =struct
type 'a t = 'a listlet em
pty () = []let add s e = e :: slet m
ember s e = List.m
em e s
end;;
let s = SetImpl.em
pty ();;SetIm
pl.add s 3;;
4
one possible type for the module
module SetIm
plC: ManifestSet =
structtype 'a t = 'a listlet em
pty () = []let add s e = e :: slet m
ember s e = List.m
em e s
end
module type M
anifestSet =sigtype 'a t = 'a list
val empty: unit -> 'a t
val add: 'a t -> 'a -> 'a tval m
ember: 'a t -> 'a -> bool
end
5
another type for the same m
odule
module SetIm
plA: O
paqueSet =struct
type 'a t = 'a listlet em
pty () = []let add s e = e :: slet m
ember s e = List.m
em e s
end
module type O
paqueSet =sigtype 'a t
val empty: unit -> 'a t
val add: 'a t -> 'a -> 'a tval m
ember: 'a t -> 'a -> bool
end
6
controlling access
let s = SetImplC.em
pty ();;SetIm
plC.add s 3;;4::s;;
let s = SetImplA
.empty ();;
SetImplA
.add s 3;;4::s;; (* type error *)
7
extending a module
module SetW
ithUnion = struct
include SetImpl
let union s1 s2 = List.append s1 s2end;;
8
substructure
suppose we w
ant a set of strings›
exploiting ordering
module O
rderedString =structtype t = string
let lt a b = a < bend;;
9
module O
rderedStringSet = structm
odule Os = O
rderedStringtype t = O
s.tlet em
pty () = []let rec add s e =
match s w
ith [] -> [e]| x :: xs -> if O
s.lt e x then e :: s else x :: add xs elet rec m
ember s e =
match s w
ith [] -> false| x :: xs -> if O
s.lt x e then false else mem
ber xs eend;;
does this satisfy the signature OpaqueSet?
10
making it generic
module type O
rdered =sig
type tval lt: t -> t -> bool
end;;
11
a functor
module O
rderedSetImpl = functor (Elt: O
rdered) ->struct
type element = Elt.t
type set = Elt.t listlet em
pty () = []let rec add s e =
match s w
ith [] -> [e]| x :: xs -> if Elt.lt e x then e :: s else x :: add xs e
let rec mem
ber s e =m
atch s with [] -> false
| x :: xs -> if Elt.lt x e then false else mem
ber xs eend;;
12
design a program›takes nam
es & phone numbers as input
›saves and restores from a file
›does lookup of number given nam
e
a small design problem
13
a generic parseable type
module type PA
RSEABLE =
sigtype tval parse: string -> tval unparse: t -> string
end;;
use parse/unparse for unmarshal/m
arshal too
14
a file module type
module type FILEFU
N =
functor (K: PA
RSEABLE) -> functor (V
: PARSEA
BLE) ->sigtype keytype = K
.ttype valuetype = V
.ttype filetypeval em
pty: unit -> filetypeval read: filetype -> (keytype, valuetype) H
ashtbl.t -> unitval w
rite: filetype -> (keytype, valuetype) Hashtbl.t -> unit
end
15
a file implem
entation
module File : FILEFU
N =
functor (K: PA
RSEABLE) -> functor (V
: PARSEA
BLE) ->struct
type keytype = K.t
type valuetype = V.t
type filetype = (string * string) list reflet em
pty () = ref [ ]let read file tbl =
let insert p =H
ashtbl.add tbl (K.parse (fst p)) (V
.parse (snd p)) inList.iter insert !file
let write file tbl =
let cons k v l = (K.unparse k, V
.unparse v) :: l infile := H
ashtbl.fold cons tbl [ ]end
16
a generic file-backed mapper
module M
apper =functor (K
: PARSEA
BLE) -> functor (V: PA
RSEABLE) ->
structm
odule KV
F = File (K) (V
)type keytype = K
.ttype valuetype = V
.tlet file = K
VF.em
pty ()let tbl = H
ashtbl.create (10)let save () = K
VF.w
rite file tbllet restore () = K
VF.read file tbl
let put k v = Hashtbl.add tbl k v
let get k = Hashtbl.find tbl k
let remove k = H
ashtbl.remove tbl k
let has k = Hashtbl.m
em tbl k
end
17
names &
phone numbers
module N
ame: PA
RSEABLE =
structtype t = stringlet parse x = xlet unparse x = x
end;;
module PhoneN
umber: PA
RSEABLE =
structtype t = {areacode: string; rest: string}let parse s =
{areacode = String.sub s 0 3; rest = String.sub s 4 7}let unparse n = String.concat "." [n.areacode ; n.rest]
end;;
18
a phonebook implem
entation
module PB =
structm
odule M = M
apper (Nam
e) (PhoneNum
ber)include Mlet enter nam
e num =
M.put (N
ame.parse nam
e) (Num
.parse num)
let lookup name =
let n = Nam
e.parse name in
if M.has n then PhoneN
umber.unparse (M
.get n)else "m
issing"end
19
using the phonebook
# PB.enter "home" "617 9644620";;
- : unit = ()# PB.lookup "hom
e";;- : string = "617.9644620"# PB.save ();;# PB.enter "office" "617 2588471";;# PB.lookup "office";;- : string = "617.2588471"# PB.enter "hom
e" "617 9999999";;# PB.restore ();;# PB.lookup "hom
e";;- : string = "617.9644620"
20
fully functorizing (1)
module type M
APPERFU
N =
functor (K: Parseable) -> functor (V
: Parseable) ->sigtype keytype = K
.ttype valuetype = V
.tval save: unit -> unitval restore: unit -> unitval put: keytype -> valuetype -> unitval get: keytype -> valuetypeval has: keytype -> boolval rem
ove: keytype -> unitend
21
fully functorizing (2)
module PBFun =functor (N
ame: PA
RSEABLE) ->
functor (Num
: PARSEA
BLE) ->functor (M
F: MA
PPERFUN
) ->struct
module M
= MF (N
ame) (N
um)
include Mlet enter nam
e num =
M.put n (N
ame.parse nam
e) (Num
.parse num)
let lookup name =
let n = Nam
e.parse name in
if M.has n then
Num
.unparse (M.get n)
else "missing"
end
22
putting it all together
module M
yPB = PBFun (Nam
e) (PhoneNum
ber) (Mapper);;
MyPB.enter "hom
e" "617 9644620";;M
yPB.lookup "home";;
23
notes
functorizing›
eliminates global references
›m
akes dependences explicit›
but parameter proliferation can be cum
bersome
Mapper
›is a singleton
›probably a bad design
object-oriented solution›
would require a separate factory class
›using serialization avoids this
but relies on extra-linguistic mechanism
and doesn’t give readable file
24
will this work?
module M
arriageRegFun =functor (M
an: PARSEA
BLE) ->functor (W
oman: PA
RSEABLE) ->
functor (MF: M
APPERFU
N) ->
structm
odule M = M
F (Man) (W
oman)
include Mlet enter a b=
let a' = Man.parse a and b' = W
oman.parse b in
M.put a' b' ; M
.put b' a'let lookup nam
e =let n = M
an.parse name in
if M.has n then
Wom
an.unparse (M.get n)
else "missing"
end;;
25
sharing constraints
module M
arriageRegFun =functor (M
an: PARSEA
BLE) ->functor (W
oman: PA
RSEABLE w
ith type t = Man.t) ->
functor (MF: M
APPERFU
N) ->
structm
odule M = M
F (Man) (W
oman)
include Mlet enter a b=
let a' = Man.parse a and b' = W
oman.parse b in
M.put a' b' ; M
.put b' a'let lookup nam
e =let n = M
an.parse name in
if M.has n then
Wom
an.unparse (M.get n)
else "missing"
end;;
26
discussion
›what does ML offer over Java?
›why aren’t sharing constraints a big deal in Java?
came up in discussion
›can a Caml m
odule have two components with sam
e name?
›apparently: yeswith m
atching or different typesin signature and structureone seem
s to shadow the other›why?