data-structuresiteratorsetocaml

Use Set.Make.iter to transform the elements of a set?


I've got a library which implements a set (interface with documentation available here: http://pastebin.com/j9QUyN1G). I understand everything apart from this fragment:

val iter : ('a -> unit) -> 'a t -> unit 
(** [iter f s] applies [f] to all elements in set [s].  The elements
    are passed to [f] in increasing order with respect to the ordering
    used to create the set. *)

So iter takes a function as one of the arguements and applies it to all elements of set. So I would expect something like ('a -> 'a) which takes an element of the set and changes it to element of the same type with other value or ('a -> 'b) which takes 'a t and transforms it to 'b t. But instead iter takes a function of type ('a -> unit) and also returns unit, not an 'a t nor 'b t.

So how should an example function passed to iter look like?


Solution

  • iter doesn't change the elements of the set. It's executed purely for its side effects. You might use it to print the elements, for example:

    module StringSet = Set.Make(String)
    …
    StringSet.iter print_endline ss
    

    The set data structure is immutable, so you can't change the elements of the set. You can build a new set whose elements are derived from an existing set. For a list, there's the function map which takes a list [x1; …; xn] and returns a new list [f x1; …; f xn]. There is no similar function in the Set module because elements in a set are not stored in the order chosen by the caller: there's no such thing as a set with its elements in an order derived from another set. If you want to build a set from the images of the elements of a set, insert the new elements one by one.

    module Int = struct
      type t = int
      let compare = Pervasives.compare
    end
    module IntSet = Set.Make(Int)
    module StringSet = Set.Make(String)
    let int_to_string_set is =
      IntSet.fold (fun i ss -> StringSet.add (string_of_int i) ss) is StringSet.empty