Тип "информация", чтобы получить больше результатов от функций - PullRequest
2 голосов
/ 20 июля 2011

Я определил некоторые сложные типы данных, например:

type drawer =
  { ...
    box: boxes list }
type table =
  { ...
    drawers: drawer list }
type room =
  { ...
    tables: table list }

И я хочу определить некоторые функции схожих целей, но с разными типами аргументов, например:

val compare_size_rooms: room -> room -> bool (* true: bigger, false: smaller *)
val compare_size_tables: table -> table -> bool
val compare_size_boxes: box -> box -> bool

Одна вещь состоит в том, что иногда, из-за различных структур, 2 комнаты / столы / коробки могут быть несопоставимыми, поэтому я надеюсь, что сравнение могло бы дать мне некоторую дополнительную информацию, помимо просто истинного или ложного.

Мой вопросявляется ли это обычным способом определения типа info:

type info =
  | Incomparable_Tables_One_foldable_Another_non_foldable
  | Incomparable_Tables_One_rectangle_Another_triangle
  | Incomparable_Boxes_One_in_paper_Another_in_metal
  | ...

И я делаю функции следующим образом:

val compare_size_rooms: room -> room -> bool * info (* true: bigger, false: smaller *)
val compare_size_tables: table -> table -> bool * info
val compare_size_boxes: box -> box -> bool * info

Так что в этих функциях я анализирую2 значения, если они сравнимы, возвращает bool, который больше или меньше, в противном случае info возвращает полезную информацию анализа.

Эта структура кажется мне не очень распространенной, может кто-нибудь сказать мне, если этоэто обычно, или реализовать то же самое, если есть лучший способ?

Большое спасибо

1 Ответ

1 голос
/ 20 июля 2011

Если сравниваемые два объекта не сопоставимы, не рекомендуется возвращать логическое значение, как если бы они были сопоставимы.Вместо этого вы можете вызвать исключение:

exception Incomparable_Tables_One_foldable_Another_non_foldable

let compare_size_tables a b = 
  if comparable a b then 
    a.size < b.size (* Or whatever you do *)
  else
    raise Incomparable_Tables_One_foldable_Another_non_foldable

(* val compare_size_tables : table -> table -> bool *)

Альтернативой является использование варианта возвращаемого типа, который может быть либо логическим (когда объекты сопоставимы), либо информационным типом (если это не так).Например, используя библиотеку «Батареи»:

open BatPervasives

type info = 
  | Incomparable_Tables_One_foldable_Another_non_foldable
  | ...

let compare_size_tables a b = 
  if comparable a b then 
    Ok (a.size < b.size) 
  else
    Bad (Incomparable_Tables_One_foldable_Another_non_foldable)

(* val compare_size_tables : table -> table -> (bool, info) BatStd.result *)

В последнем случае вам потребуется match независимо от того, был ли результат Bad info или Ok boolean.

...