(* Given a set of integer lists, compute all sets obtained taking the head of
 * a list and adding it in front of another list, or as a new separate list *)

module type PRINTABLE = sig    (* type that can be printed and compared *)
  type t
  val compare: t -> t -> int   (* needed to make sets of this type *)
  val print: t -> unit
end

module ExtSet(Elt: PRINTABLE) = struct  (* set with printable elements *)
  include Set.Make(Elt)         (* includes all standard set functions *)
  let print s = print_char '{';
    if not (is_empty s) then let m = min_elt s in (
      Elt.print m;
      iter (fun e -> print_string ", "; Elt.print e) (remove m s)
    ); print_char '}'
  let replace eo en s = add en (remove eo s)    (* new: replace function *)
end

module IntList = struct         (* integer lists that can be printed *)
  type t = int list
  let compare = compare         (* need (default) comparison to make set *)
  let print l = print_char '['; if l <> [] then (
      print_int (List.hd l);
      List.iter (fun e -> print_string "; "; print_int e) (List.tl l)
    ); print_char ']'
end

module S = ExtSet(IntList)      (* printable set of integer lists *)
module SS = ExtSet(S)           (* set of sets *)

(* actual solution starts here *)
let comp f g x = f (g x)        (* function composition *)
(* union of f applied to each set element *)
let map2s f s = S.fold (comp SS.add f) s SS.empty       (* f -> set *)
let map2ss f s = S.fold (comp SS.union f) s SS.empty    (* f -> set of sets *)

(* adds i in turn to each list in s *)
let addtoall i s = map2s (fun l -> S.replace l (i::l) s) s

let allsets s =         (* all sets obtainable from current one *)
  SS.remove s (map2ss (fun lst ->    (* remove original set from result *)
    let h = List.hd lst in match List.tl lst with       (* for each list head *)
        [] -> addtoall h (S.remove lst s)       (* if sole element, remove *)
      | t -> let rem = S.replace lst t s in     (* else replace with tail *)
             SS.add (S.add [h] rem) (addtoall h rem)) s)    (* and add set with [h] *)

let testset = S.add [3] (S.singleton [1;2]);;

SS.print (allsets testset);;


This document was generated using caml2html