OCaml: Set modules

偶尔善良 提交于 2019-12-03 22:37:31

Sets are defined using a functorial interface. For any given type, you have to create a Set module for that type using the Set.Make functor. An unfortunate oversight of the standard libraries is that they don't define Set instances for the built-in types. In most simple cases, it's sufficient to use Pervasives.compare. Here's a definition that works for int:

module IntSet = Set.Make( 
  struct
    let compare = Pervasives.compare
    type t = int
  end )

The module IntSet will implement the Set.S interface. Now you can operate on sets using the IntSet module:

let s = IntSet.empty ;;
let t = IntSet.add 1 s ;;
let u = IntSet.add 2 s ;;
let tu = IntSet.union t u ;;

Note that you don't have to explicitly define the input structure for Set.Make as an OrderedType; type inference will do the work for you. Alternatively, you could use the following definition:

module IntOrder : Set.OrderedType = struct
  type t = int
  let compare = Pervasives.compare
end

module IntSet = Set.Make( IntOrder )

This has the advantage that you can re-use the same module to instantiate a Map:

module IntMap = Map.Make( IntOrder )

You lose some genericity in using functors, because the type of the elements is fixed. For example, you won't be able to define a function that takes a Set of some arbitrary type and performs some operation on it. (Luckily, the Set module itself declares many useful operations on Sets.)

In addition to Chris's answer, it may be useful to say that some standard library modules already adhere to the OrderedType signature. For example, you can simply do:

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 *)

And so on.

Here's a simple usage example for StringSet; remember that sets are functional data structures, so adding a new element to a set returns a new set:

let set = List.fold_right StringSet.add ["foo";"bar";"baz"] StringSet.empty ;;
StringSet.mem "bar" set ;; (* returns true *)
StringSet.mem "zzz" set ;; (* returns false *)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!