Это довольно хакерский (и приводит к предупреждению), но вы можете использовать Obj
, чтобы проверить, равны ли теги или нет. Он должен отлавливать все случаи, когда a и b имеют разные значения:
type data = | States of int array
| Chars of (char list) array
let median a b = match a,b with
| States xs, States ys ->
assert( (Array.length xs) = (Array.length ys) );
States (Array.init (Array.length xs) (fun i -> xs.(i) lor ys.(i)))
| Chars xs, Chars ys ->
assert( (Array.length xs) = (Array.length ys) );
let union c1 c2 = (List.filter (fun x -> not (List.mem x c2)) c1) @ c2 in
Chars (Array.init (Array.length xs) (fun i -> union xs.(i) ys.(i)))
(* inconsistent pairs of matching *)
| x, y when (Obj.tag (Obj.repr x)) <> (Obj.tag (Obj.repr y)) -> assert false
Предупреждение относится к неисчерпывающему сопоставлению с образцом (поскольку он не может определить, соответствует ли охраняемое предложение остальным или нет).
РЕДАКТИРОВАТЬ: вам вообще не нужно использовать Obj, вы можете просто сравнить x и y напрямую:
| x, y when x <> y -> assert false
Хотя, к сожалению, это все равно приводит к предупреждению.