I have a set of ints whose input I'd like to restrict. I would like it to behave something like the following:
# RestrictedIntSet.add 15 (RestrictedIntSet.make 0 10)
Exception: 15 out of acceptable range [0 .. 10]
How can I implement this? In Java, it could look something like:
Set<Integer> restrictedSet = new HashSet<Integer>() {
public boolean add(Integer i) {
if (i < lowerBound || i > upperBound) {
throw new IllegalArgumentException("out of bounds");
}
return super.add(i);
}
Or, to be less abusing of inheritance:
public class RestrictedSet {
private int lowerBound;
private int upperBound;
private Set elems = Sets.newHashSet();
public RestrictedSet(int lowerBound, int upperBound) {
this.lowerBound = lowerBound;
this.upperBound = upperBound;
}
public boolean add(Integer i) {
if (i < lowerBound || i > upperBound) {
throw new IllegalArgumentException("out of bounds");
}
return elems.add(i);
}
/* fill in other forwarded Set calls as needed */
}
What is the equivalent, idiomatic way to do this in OCaml?
Well, it depends, which set library are you using?
Using the Set module of the standard library, you could do the following:
module type RestrictedOrderedType = sig
type t
val compare : t -> t -> int
val lower_bound : t
val upper_bound : t
end
module RestrictedSet (Elem : RestrictedOrderedType) = struct
include Set.Make(Elem)
exception Not_in_range of Elem.t
let check e =
if Elem.compare e Elem.lower_bound < 0
|| Elem.compare e Elem.upper_bound > 0
then raise (Not_in_range e)
else e
(* redefine a new 'add' in term of the one in Set.Make(Elem) *)
let add e s = add (check e) s
let singleton e = singleton (check e)
end
(* test *)
module MySet = RestrictedSet(struct
type t = int
let compare = compare
let lower_bound = 0
let upper_bound = 10
end)
let test1 = MySet.singleton 3
let test2 = MySet.add (-3) test1
(* Exception: Not_in_range (-3) *)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With