ML modules Daniel Jackson MIT Lab for Computer Science 6898: - - PowerPoint PPT Presentation

ml modules
SMART_READER_LITE
LIVE PREVIEW

ML modules Daniel Jackson MIT Lab for Computer Science 6898: - - PowerPoint PPT Presentation

ML modules Daniel Jackson MIT Lab for Computer Science 6898: Advanced Topics in Software Design March 20, 2002 to topics fo ics for to r today ay elements of ML module language structs: modules, export types and values


slide-1
SLIDE 1

ML modules

Daniel Jackson MIT Lab for Computer Science 6898: Advanced Topics in Software Design March 20, 2002

slide-2
SLIDE 2 2

to topics fo ics for to r today ay

elements of ML module language › structs: modules, export types and values › signatures: types for modules › functors: functions from modules to modules signature ascription › controlling client’s view of a module functorization › making dependences explicit

slide-3
SLIDE 3 3

set im set implem lementation def and use entation def and use

module SetImpl = struct type 'a t = 'a list let empty () = [] let add s e = e :: s let member s e = List.mem e s end;; let s = SetImpl.empty ();; SetImpl.add s 3;;

slide-4
SLIDE 4 4
  • ne
  • ne pos
  • ssible

ible typ type e for

  • r the

the module module

module SetImplC: ManifestSet = struct type 'a t = 'a list let empty () = [] let add s e = e :: s let member s e = List.mem e s end module type ManifestSet = sig type 'a t = 'a list val empty: unit -> 'a t val add: 'a t -> 'a -> 'a t val member: 'a t -> 'a -> bool end

slide-5
SLIDE 5 5

another typ another type for the same module e for the same module

module SetImplA: OpaqueSet = struct type 'a t = 'a list let empty () = [] let add s e = e :: s let member s e = List.mem e s end module type OpaqueSet = sig type 'a t val empty: unit -> 'a t val add: 'a t -> 'a -> 'a t val member: 'a t -> 'a -> bool end

slide-6
SLIDE 6 6

controlling access controlling access

let s = SetImplC.empty ();; SetImplC.add s 3;; 4::s;; let s = SetImplA.empty ();; SetImplA.add s 3;; 4::s;; (* type error *)

slide-7
SLIDE 7 7

extending a module extending a module

module SetWithUnion = struct include SetImpl let union s1 s2 = List.append s1 s2 end;;

slide-8
SLIDE 8 8

substructure substructure

suppose we want a set of strings › exploiting ordering module OrderedString = struct type t = string let lt a b = a < b end;;

slide-9
SLIDE 9 9

module OrderedStringSet = struct module Os = OrderedString type t = Os.t let empty () = [] let rec add s e = match s with [] -> [e] | x :: xs -> if Os.lt e x then e :: s else x :: add xs e let rec member s e = match s with [] -> false | x :: xs -> if Os.lt x e then false else member xs e end;; does this satisfy the signature OpaqueSet?

slide-10
SLIDE 10 10

making it generic aking it generic

module type Ordered = sig type t val lt: t -> t -> bool end;;

slide-11
SLIDE 11 11

a functor functor

module OrderedSetImpl = functor (Elt: Ordered) -> struct type element = Elt.t type set = Elt.t list let empty () = [] let rec add s e = match s with [] -> [e] | x :: xs -> if Elt.lt e x then e :: s else x :: add xs e let rec member s e = match s with [] -> false | x :: xs -> if Elt.lt x e then false else member xs e end;;

slide-12
SLIDE 12 12

design a program › takes names & phone numbers as input › saves and restores from a file › does lookup of number given name

a small design p a small design problem roblem

slide-13
SLIDE 13 13

a generic parseable type a generic parseable type

module type PARSEABLE = sig type t val parse: string -> t val unparse: t -> string end;; use parse/unparse for unmarshal/marshal too

slide-14
SLIDE 14 14

a file module typ a file module type

module type FILEFUN = functor (K: PARSEABLE) -> functor (V: PARSEABLE) -> sig type keytype = K.t type valuetype = V.t type filetype val empty: unit -> filetype val read: filetype -> (keytype, valuetype) Hashtbl.t -> unit val write: filetype -> (keytype, valuetype) Hashtbl.t -> unit end

slide-15
SLIDE 15 15

a a file file im implem lementation entation

module File : FILEFUN = functor (K: PARSEABLE) -> functor (V: PARSEABLE) -> struct type keytype = K.t type valuetype = V.t type filetype = (string * string) list ref let empty () = ref [ ] let read file tbl = let insert p = Hashtbl.add tbl (K.parse (fst p)) (V.parse (snd p)) in List.iter insert !file let write file tbl = let cons k v l = (K.unparse k, V.unparse v) :: l in file := Hashtbl.fold cons tbl [ ] end

slide-16
SLIDE 16 16

a generic file-backed mapper a generic file-backed mapper

module Mapper = functor (K: PARSEABLE) -> functor (V: PARSEABLE) -> struct module KVF = File (K) (V) type keytype = K.t type valuetype = V.t let file = KVF.empty () let tbl = Hashtbl.create (10) let save () = KVF.write file tbl let restore () = KVF.read file tbl let put k v = Hashtbl.add tbl k v let get k = Hashtbl.find tbl k let remove k = Hashtbl.remove tbl k let has k = Hashtbl.mem tbl k end

slide-17
SLIDE 17 17

names & phone numbers names & phone numbers

module Name: PARSEABLE = struct type t = string let parse x = x let unparse x = x end;; module PhoneNumber: PARSEABLE = struct type 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;;

slide-18
SLIDE 18 18

a a pho hone nebook im imple lementatio ntation

module PB = struct module M = Mapper (Name) (PhoneNumber) include M let enter name num = M.put (Name.parse name) (Num.parse num) let lookup name = let n = Name.parse name in if M.has n then PhoneNumber.unparse (M.get n) else "missing" end

slide-19
SLIDE 19 19

using using the the p pho hone nebo book

# PB.enter "home" "617 9644620";;

  • : unit = ()

# PB.lookup "home";;

  • : string = "617.9644620"

# PB.save ();; # PB.enter "office" "617 2588471";; # PB.lookup "office";;

  • : string = "617.2588471"

# PB.enter "home" "617 9999999";; # PB.restore ();; # PB.lookup "home";;

  • : string = "617.9644620"
slide-20
SLIDE 20 20

fully functo fully functorizing rizing (1) (1)

module type MAPPERFUN = functor (K: Parseable) -> functor (V: Parseable) -> sig type keytype = K.t type valuetype = V.t val save: unit -> unit val restore: unit -> unit val put: keytype -> valuetype -> unit val get: keytype -> valuetype val has: keytype -> bool val remove: keytype -> unit end

slide-21
SLIDE 21 21

fully functorizing (2) fully functorizing (2)

module PBFun = functor (Name: PARSEABLE) -> functor (Num: PARSEABLE) -> functor (MF: MAPPERFUN) -> struct module M = MF (Name) (Num) include M let enter name num = M.put n (Name.parse name) (Num.parse num) let lookup name = let n = Name.parse name in if M.has n then Num.unparse (M.get n) else "missing" end

slide-22
SLIDE 22 22

putting it all together putting it all together

module MyPB = PBFun (Name) (PhoneNumber) (Mapper);; MyPB.enter "home" "617 9644620";; MyPB.lookup "home";;

slide-23
SLIDE 23 23

no notes tes

functorizing › eliminates global references › makes dependences explicit › but parameter proliferation can be cumbersome Mapper › is a singleton › probably a bad design

  • bject-oriented solution

› would require a separate factory class › using serialization avoids this but relies on extra-linguistic mechanism and doesn’t give readable file

slide-24
SLIDE 24 24

will this work? will this work?

module MarriageRegFun = functor (Man: PARSEABLE) -> functor (Woman: PARSEABLE) -> functor (MF: MAPPERFUN) -> struct module M = MF (Man) (Woman) include M let enter a b= let a' = Man.parse a and b' = Woman.parse b in M.put a' b' ; M.put b' a' let lookup name = let n = Man.parse name in if M.has n then Woman.unparse (M.get n) else "missing" end;;

slide-25
SLIDE 25 25

sh sharing constraints aring constraints

module MarriageRegFun = functor (Man: PARSEABLE) -> functor (Woman: PARSEABLE with type t = Man.t) -> functor (MF: MAPPERFUN) -> struct module M = MF (Man) (Woman) include M let enter a b= let a' = Man.parse a and b' = Woman.parse b in M.put a' b' ; M.put b' a' let lookup name = let n = Man.parse name in if M.has n then Woman.unparse (M.get n) else "missing" end;;

slide-26
SLIDE 26 26

dis discus cussion ion

› what does ML offer over Java? › why aren’t sharing constraints a big deal in Java? came up in discussion › can a Caml module have two components with same name? › apparently: yes with matching or different types in signature and structure

  • ne seems to shadow the other

› why?