Как проверить, созданы ли два значения с одним и тем же конструктором? - PullRequest
5 голосов
/ 29 июня 2011

допустим, у меня есть

type t = A of int | B of int

let xx = A(2);;
let yy = A(3);;

и я хочу проверить, равны ли конструкторы xx и yy, есть ли простой способ сделать это?Вместо того, чтобы

match xx with
  A _ ->
  (match yy with A _ -> true | B _ -> false)
| B _ -> 
  (match yy with A _ -> false | B _ -> true);;

, что становится довольно грязно, когда много типов конструкторов

Ответы [ 3 ]

8 голосов
/ 29 июня 2011

Вы можете переписать вышеупомянутое, несколько проще:

match xx, yy with
| A _, A _
| B _, B _ -> true
| (A _ | B _), _ -> false

, но я не знаю решения без перечисления всех конструкторов.

6 голосов
/ 30 июня 2011

Это возможно через модуль Obj.Анализ объектов с помощью функций Obj, если все сделано правильно, не приведет к сбою вашей программы;но вы должны быть осторожны, если хотите получить значимые результаты.

let equal_constructors (x : 'a) (y : 'a) =
  let r = Obj.repr x and s = Obj.repr y in
  if Obj.is_int r && Obj.is_int s then (Obj.obj r : int) = (Obj.obj s : int) else
  if Obj.is_block r && Obj.is_block s then Obj.tag r = Obj.tag s else
  false

При вызове значений типа варианта (не полиморфного типа варианта) эта функция возвращает true, если оба значенияимеют одинаковый конструктор с нулевым аргументом или оба имеют одинаковый конструктор с 1 или более аргументами, и false в противном случае.Система типов не помешает вам использовать equal_constructors в других типах;вы получите true или false возвращаемое значение, но не обязательно значащее.

4 голосов
/ 01 июля 2011

Другой способ сделать это, который может работать хорошо, - создать другой тип, соответствующий тегам, и использовать этот тип.

type t = A of int | B of int
module Tag = struct type t = A | B end

let to_tag = function A _ -> Tag.A | B _ -> Tag.B
let tags_are_equal x y =
    to_tag x = to_tag y
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...