I have some type
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
;;
And I know that I have issue in my code, if p >= q in B (p, q) or A (p, q). So I want to make assertion in type, such that if I'll try to make A (5, 1) it will inform me.
Is it possible to make assertion in type constructor? How it should look like?
I'm trying to avoid something like that:
assert (p < q) ; A(p, q)
Cause I have a lot of A or B objects in code.
@Jeffrey Scofield already gave a fully accurate answer to this, but here is the example requested:
module type MY_TYPE =
sig
type my_type_name = private
| A of (float * float)
| B of (float * float)
| E
val a : float -> float -> my_type_name
val b : float -> float -> my_type_name
val e : my_type_name
end
module My_type : MY_TYPE =
struct
type my_type_name =
| A of (float * float)
| B of (float * float)
| E
let a p q = assert true; A (p, q)
let b p q = assert true; B (p, q)
let e = E
end
let () =
(* My_type.A (1., 2.); *) (* Type error - private type. *)
let x = My_type.a 1. 2. in
(* Can still pattern match. *)
match x with
| My_type.A (_, _) -> ()
| My_type.B (_, _) -> ()
| My_type.E -> ()
The body of the signature could be an .mli file instead and the body of My_type could be an .ml file. The key is that my_type_name is followed by the keyword private in MY_TYPE. This causes the direct use of the constructor at the bottom to be flagged as an error, forcing all construction to go through the functions a, b, e, where you can include assertions or arbitrary other expressions.
EDIT To make the functions look even more like the constructors, you can of course turn their arguments into tuple types. To make the module nearly transparent you can open it at the bottom. But these are matters of taste and up to you.
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