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
(a) [5 pts]
Based on the implementations of the operations other than
remove
, give the rep invariant and
abstraction function for this implementation.
Answer:
(* AF:
*
AF(ref l) = AF’(l)
* where
*
AF’([]) = Ø
*
AF’({elem = x, count = n}::t) = AF’(t)
∪
{x, x, .
.., x}
*
(n copies of x; the operator
∪
denotes bag union.)
*
* RI:
*
1. No element elem appears twice in different list elements.
*
2. The count in each list element is positive.