I want to determine the type so that the whole structure goes through the members of the module, which can preserve invariants, but allow you to destruct template matching.
I'm just learning OCaml, but the following almost works for an int pair with an invariant that the left should be strictly less than the right
module Range : sig type t = private { left:int; right:int } exception InvalidRange of (int*int) val make : int -> int -> t end = struct type t = { left:int; right:int } exception InvalidRange of (int*int) let make left right = if left < right then { left; right } else raise (InvalidRange (left, right)) end
which works this way
# let p = Range.make 1 2;; val p : Range.t = {Range.left = 1; Range.right = 2}
and destructive work after fashion
# let {Range.left=x; Range.right=y} = p;; val x : int = 1 val y : int = 2
when building crash
# let badp = {Range.left = 2; Range.right = 1};; let badp = {Range.left = 2; Range.right = 1};; Error: Cannot create values of the private type Range.t
but what I really would like to do is the syntactic convenience of destructuring tuples. Below does not work:
module Range : sig type t = private int*int exception InvalidRange of (int*int) val make : int -> int -> t end = struct type t = int*int exception InvalidRange of (int*int) let make left right = if left < right then (left, right) else raise (InvalidRange (left, right)) end
but then I cannot destroy it using the tuple template:
# let r = Range.make 1 2 ;; val r : Range.t = (1, 2)
I could change the type to type t = R of (int * int)
, but I need them to be as light as possible in memory size. Any ideas?