2.
Speciﬁcation and veriﬁcation
[19 pts]
(parts a–d)
The following is the interface and a partial implementation of a data abstraction. Unfortunately the implementer
was a little confused about the rep invariant and abstraction function, and has gotten off to a bad start. (This
code is also reproduced on page 12, which can be detached for easy reference.)
signature BAG = sig
(* A bag (or multiset) is a unordered collection of elements in which
* a given element can appear any number of times. This sig is an
* interface for a mutable bag of integers.
* Examples: Ø, {0}, {-1, 10, 10} *)
type bag
(* create() is a new empty bag {} *)
val create: unit -> bag
(* empty(b) is whether b is empty *)
val empty: bag -> bool
(* contains(b, x) is whether x is in b *)
val contains: bag * int -> bool
(* Effects: add(b, x) adds one appearance of x to b.
Examples: add({1}, 0) = {0, 1}, add({2}, 2) = {2,2} *)
val add: bag * int -> unit
(* remove(b,x) is b with one appearance of element x removed.
* Examples: After remove(b, 0) with b = {0,0,1}, b = {0, 1}.
*
After remove(b, 0) with b = {1}, b = {1}. *)
val remove: bag * int -> unit
end
structure Bag :> BAG = struct
type bag = {elem: int, count: int} list ref
fun create() = ref []
fun empty(b) = case !b of [] => true | _ => false
fun contains(b, x) =
List.exists (fn ({elem = x’, count = _}) => x = x’) (!b)
fun add(b, x) = .
..
fun remove(b, x) =
if contains(b, x) then
b := map (fn ({elem = x’, count = n}) =>
if x = x’ then {elem = x’, count = n-1}
else {elem = x’, count = n}) (!b)
else ()
end
3