Others already pointed out to a link that uses sequence expressions and enumerates the sets lazily. That's how I would solve the problem (note that there is nothing impure or non-functional about using for
inside sequence comprehension - it is just a way to generate sequence of results):
let rec powerset s = seq {
match s with
| [] -> yield []
| h::t -> for x in powerset t do yield! [x; h::x] }
That said, this can be easily translated to code that returns a list and uses higher-order functions:
let rec powerset =
function
| [] -> [[]]
| x::xs -> List.collect (fun subset -> [subset; x::subset]) (powerset xs)
The power set of an empty set is a set with single element []
(note that this is wrong in your snippet). To generate a powerset of x::xs
, we first generate powerset of xs
and then return two sets for every single element of the generated powerset - one is the sub set and the other is the subset with added x
element. (This is done using List.collect
which is like calling List.map
followed by List.concat
.)