I am trying to get a function (given as a parameter a set) to return a set whose elements are all the subset formed from the main set. Ex: {1;2;3} -> { {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3} }
But I don't exactly know how to make a module that lets me work with a set of sets. What type should I define it as?
A set of all subsets is called a power set. To implement an algorithm you don't really need a special data structure, as you can represent a set with a list. Correspondingly a set of sets would be a list of lists. E.g.,
let rec powerset = function | [] -> [[]] | x :: xs -> let ps = powerset xs in ps @ List.map (fun ss -> x :: ss) ps
And here is an example of usage:
powerset [1;2;3];;
- : int list list = [[]; [1]; [2]; [2; 1]; [3]; [3; 1]; [3; 2]; [3; 2; 1]]
If you want to use real sets, like Jeffrey suggested. Then we will need to adapt the algorithm a little bit, since Set module provides a little bit different interface.
module S = Set.Make(String)
module SS = Set.Make(S) let powerset xs = S.fold (fun x ps -> SS.fold (fun ss -> SS.add (S.add x ss)) ps ps) xs (SS.singleton S.empty)
To run the algorithm and to print the result we need to transform it back to a list, since the OCaml toplevel doesn't know how to print sets:
# powerset (S.of_list ["1"; "2"; "3"])
|> SS.elements
|> List.map S.elements;;
- : S.elt list list =
[[]; ["1"]; ["1"; "2"]; ["1"; "2"; "3"]; ["1"; "3"]; ["2"]; ["2"; "3"];
["3"]]
Now, we can generalize algorithm, so that it will work on any ordered type.
module Powerset(T : Set.OrderedType) = struct module S = Set.Make(T)
module SS = Set.Make(S) let of_set xs = S.fold (fun x ps -> SS.fold (fun ss -> SS.add (S.add x ss)) ps ps) xs (SS.singleton S.empty) end
Now we can run it:
# module Powerset_of_strings = Powerset(String);;
# open Powerset_of_string;;
# of_set (S.of_list ["1"; "2"; "3"])
|> SS.elements
|> List.map S.elements;;
- : S.elt list list =
[[]; ["1"]; ["1"; "2"]; ["1"; "2"; "3"]; ["1"; "3"]; ["2"]; ["2"; "3"];
["3"]]