Я хочу использовать OCaml для создания наборов данных и сравнения между ними. Я видел документацию по типам модулей типа Set.OrderType, Set.Make и т.д., Но я не могу понять, как инициализировать набор или иным образом использовать их.
OCaml: установка модулей
Ответ 1
Наборы определяются с использованием функториального интерфейса. Для любого заданного типа вам необходимо создать модуль Set для этого типа с помощью функтора Set.Make. Несчастный надзор над стандартными библиотеками заключается в том, что они не определяют экземпляры Set для встроенных типов. В большинстве простых случаев достаточно использовать Pervasives.compare. Здесь определение, которое работает для int:
module IntSet = Set.Make(
struct
let compare = Pervasives.compare
type t = int
end )
Модуль IntSet реализует интерфейс Set.S. Теперь вы можете работать с наборами с помощью модуля IntSet:
let s = IntSet.empty ;;
let t = IntSet.add 1 s ;;
let u = IntSet.add 2 s ;;
let tu = IntSet.union t u ;;
Обратите внимание, что вам не нужно явно определять структуру ввода для Set.Make как OrderedType; тип вывода сделает работу за вас. В качестве альтернативы вы можете использовать следующее определение:
module IntOrder : Set.OrderedType = struct
type t = int
let compare = Pervasives.compare
end
module IntSet = Set.Make( IntOrder )
Это имеет то преимущество, что вы можете повторно использовать тот же модуль для создания экземпляра Map:
module IntMap = Map.Make( IntOrder )
Вы теряете некоторую универсальность при использовании функторов, потому что тип элементов исправлен. Например, вы не сможете определить функцию, которая принимает Set какого-либо произвольного типа и выполняет некоторую операцию над ней. (К счастью, сам модуль Set объявляет много полезных операций над Set s.)
Ответ 2
В дополнение к Крису, может быть полезно сказать, что некоторые стандартные библиотечные модули уже привязаны к подписи OrderedType. Например, вы можете просто сделать:
module StringSet = Set.Make(String) ;; (* sets of strings *)
module Int64Set = Set.Make(Int64) ;; (* sets of int64s *)
module StringSetSet = Set.Make(StringSet) ;; (* sets of sets of strings *)
И так далее.
Вот простой пример использования для StringSet; помните, что наборы являются функциональными структурами данных, поэтому добавление нового элемента в набор возвращает новый набор:
let set = List.fold_right StringSet.add ["foo";"bar";"baz"] StringSet.empty ;;
StringSet.mem "bar" set ;; (* returns true *)
StringSet.mem "zzz" set ;; (* returns false *)