1

I want to find the Powerset

powerset [1;2;3] = = [[]; [3]; [2]; [2; 3]; [1]; [1; 3]; [1; 2]; [1; 2; 3]]

let rec powerset = function
    | [] -> []
    | x::xs -> List.map (fun ys -> xs) xs::powerset (xs)

I am having trouble with the code, this is what my output looks like now.

val it : int list list list = [[[2; 3]; [2; 3]]; [[3]]; []]

Mike John
  • 818
  • 4
  • 11
  • 29
  • possible duplicate of [Generate powerset lazily](http://stackoverflow.com/questions/8164364/generate-powerset-lazily) – Jack P. May 29 '13 at 23:44
  • If you look at the link you are providing then you will see that the question is for a sequence of sets. My question is for the power set of one list. – Mike John May 30 '13 at 00:14
  • @MikeJohn Your question doesn't *specifically* ask about F# 3.0 features, or about how to use F# from a scripting standpoint (i.e., writing shell scripts in an `*.fsx` file), which is why I removed the tags. Is there any special reason you think they should be applied? – Jack P. May 30 '13 at 00:37
  • @MikeJohn did you look at Gene's link? As far as I can tell, it answers your question exactly. – Jack P. May 30 '13 at 00:38
  • I don't want to use recursion and a for loop. I also found the way of providing the link to be offensive, at first I thought it was a link to Google not a link to my question. – Mike John May 30 '13 at 01:28
  • @MikeJohn If you found that link before, then it would be good to reference it from your question and say why that's not what you want. That would help to clarify the question and you would get the answer you need. Otherwise, I can fully understand why people just point you to a link with some solution that is easy to find online... – Tomas Petricek May 30 '13 at 01:35
  • @TomasPetricek You are right, providing links before posting is extremely helpful. I never said I found the link from Jack.P before posting, though. – Mike John May 30 '13 at 01:45

1 Answers1

3

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

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • How does that for behave in F#? Coming from C#, I keep thinking it is a foreach x in the powerset . – Mike John May 30 '13 at 01:34
  • If you're coming from C#, then you can think of `seq { .. }` as an iterator method and `yield` corresponds to `yield return` (`for` means the same thing as `foreach`, but inside iterator block, it is just generating elements - not doing any mutation) – Tomas Petricek May 30 '13 at 01:38
  • Can you expand on that i tried | x::xs -> List.map (List.concat (fun ss -> [ss; x::ss])) (powerset xs);; and get a'-> b list when it is looking for a b list. – SuperCell Apr 28 '16 at 00:34