2015-12-29 5 views

ответ

4

Полиморфный сравнить функция работает рекурсивно исследовать структуру ценностей, обеспечивая одноранговой общее упорядочение значений OCaml, используемых для определения структурного равенства протестирована полиморфного оператора =.

Это не по определению функции и затворы, как указано в @antron. Рекурсивный характер определения означает, что структурное равенство не определено для значений, содержащих функцию или замыкание. Этот рекурсивный характер также подразумевает, что функция сравнивается с функцией не на рекурсивных значениях, как упоминается также @antron.

Структурное равенство, и, следовательно, сравнить функции и операторы сравнения, не знает о структурных инвариантов и не может быть использована для сравнения (говоря) расширенные структуры данных, такие как наборы, Карты, HashTbls и так далее. Если желательно сравнить эти структуры, необходимо написать специализированную функцию, поэтому Set и Map определяют такую ​​функцию.

При определении собственных структур, хорошее эмпирическом правило различать между

  • конкретных типами, которые определены только в терминах примитивных типов и других конкретных типов. Конкретные типы не должны использоваться для структур, обработка которых ожидает некоторых инвариантов, так как легко создавать произвольные значения этого типа, нарушающие эти инварианты. Для этих типов подходят функции и функции полиморфного сравнения.

  • абстрактные типы, чье конкретное определение скрыто. Для этих типов лучше всего обеспечить специализированную функцию сравнения. mixture library определяет compare mixin, который может использоваться для вывода операторов сравнения из реализации специализированной функции , сравнивающей. Его использование проиллюстрировано в README.

5

Это не работает для типов функций:

# compare (fun x -> x) (fun x -> x);; 
Exception: Invalid_argument "equal: functional value". 

Аналогично, он не будет (как правило) работают для других типов, значения которых могут содержать функции:

# type t = A | B of (int -> int);; 
type t = A | B of (int -> int) 
# compare A A;; 
- : int = 0 
# compare (B (fun x -> x)) A;; 
- : int = 1 
# compare (B (fun x -> x)) (B (fun x -> x));; 
Exception: Invalid_argument "equal: functional value". 

Он также Безразлично» т (в целом) работают для рекурсивных значений:

# type t = {self : t};; 
type t = { self : t; } 
# let rec v = {self = v};; 
val v : t = {self = <cycle>} 
# let rec v' = {self = v'};; 
val v' : t = {self = <cycle>} 
# compare v v;; 
- : int = 0 
# compare v v';; 
(* Does not terminate. *) 

Thes e случаи также перечислены в documentation для compare в Pervasives.

+4

Также полиморфные 'compare' и' = 'не работают 'для значений, которые могут иметь разные представления, например типы, полученные в результате применения' Set' или 'Map'. –

+0

Это тоже не работает для объектов. Он сравнивает уникальный числовой идентификатор каждого объекта.Таким образом, сравнение двух объектов, которые физически различаются, такие как «сравнение (конец объекта) (конец объекта)' никогда не возвращает 0. –

+0

@PascalCuoq, MartinJambon: Но это зависит от вашего определения «работа». Они никогда не гарантировали, что это будет следовать вашей концепции равенства. Это просто нужно следовать некоторым (неуказанным) последовательным заказам. – newacct

Смежные вопросы