2009-09-20 2 views
16

Я хочу использовать OCaml для создания наборов данных и сравнения между ними. Я видел документацию по типам модулей, например Set.OrderType, Set.Make и т. Д., Но я не могу понять, как инициализировать набор или иным образом использовать их.OCaml: Установить модули

ответ

28

Наборы определяются с использованием функториального интерфейса. Для любого данного типа вам необходимо создать модуль 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 с.)

+1

«вы не сможете определить функцию, которая принимает набор некоторого произвольного типа» вы могли бы, однако, выполните то же самое, определив функцию внутри функтора, которая принимает ваш конкретный модуль Set в качестве параметра. но использовать его, конечно, программисту пришлось бы сделать еще один модуль с этим функтором, поэтому он менее удобен. – newacct

+0

Право. Это функторы полностью вниз. –

9

В дополнении к ответу Криса, это может быть полезно, чтобы сказать, что некоторые стандартные библиотечные модули уже придерживаются 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 *) 
Смежные вопросы