Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Altering module behavior in OCaml

Tags:

java

ocaml

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?

like image 394
Nick Heiner Avatar asked Jul 04 '26 13:07

Nick Heiner


1 Answers

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) *)
like image 163
gasche Avatar answered Jul 07 '26 02:07

gasche



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!