views:

126

answers:

1

I'm unexpectedly having a bit of trouble with going from a list of 'a option down to a list containing only the elements that are Some.

My initial attempt was:

    let ga = List.filter (fun xx ->
        match xx with
        | Some(g) -> true
        | None -> false) gao 

But of course, this result type is still 'a option list. I don't know how to use List.map to condense this, because you have to handle all cases in a match statement. I have an ugly solution, but I'm wondering if there is something better.

Ugly:

    let rec gOptRemove gdec gacc = 
        match gdec with 
        | head :: tail -> 
            match head with 
            | Some(a) -> gOptRemove tail (a :: gacc)
            | None -> gOptRemove tail gacc
        | [] -> gacc

I would prefer to find a non-recursive solution or find out what the standard way is for this kind of thing.

+16  A: 

Simply

List.choose id

as in

> [Some 4; None; Some 2; None] |> List.choose id;;
val it : int list = [4; 2]

http://msdn.microsoft.com/en-us/library/ee353456.aspx

http://msdn.microsoft.com/en-us/library/ee353607.aspx

Brian
Wow, that was easy. Had no idea that function existed.
Tony Peterson
The reason this works: List.choose wants to turn an `'a` into a `b option`. `id` is suitable for this because it turns a `'c option` into a `'c option`.
Tim Robinson
...wow, that's clever. Is this how your brain thinks all the time?
YotaXP
Just let the types guide you. You want a function that contains `option` in its signature but returns just a `list` (not a list of options). Look though the API (http://msdn.microsoft.com/en-us/library/ee353738.aspx ), and there's only one such function, `choose`, and now you're already 95% the way there.
Brian
Hm, as an aside, this appears to be my 1000th answer on stackoverflow. I hope it is worthy of the honor. :)
Brian
I read up on choose and replaced an earlier List.map with choose. Its a neat function when dealing with potential not-found or missing results. Grats on the 1000th answer.
Tony Peterson
GTK, I was also using similar code: `fun s -> s |> Seq.filter Option.isSome |> Seq.map (function Some(e) -> e | _ -> failwith "")`
Stringer Bell
@Brian thanks for all your helpful answers!
gradbot
@Brian, this is a good candidate as an answer here: http://stackoverflow.com/questions/1720318/examples-of-functional-programs-writing-themselves-via-type-analysis
Benjol
@Benjol: Indeed, added it.
Brian
@Brian, keep on shining you crazy diamond!
Dan Fitch