Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Folding list of options

Tags:

optional

f#

fold

Given a list [Some 1; Some 2; Some 3] I would like an output Some 6 . Given a list [Some 1; None] should yield None.

But I'm finding it a bit more difficult than I had imagined to achieve this in a clean way.

The best I could come up with was this

let someNums = [Some 1; Some 2; Some 3]
someNums 
|> List.reduce (fun st v ->
  Option.bind (fun x ->
    Option.map (fun y -> x + y) st) v )
like image 261
Overly Excessive Avatar asked Mar 05 '16 10:03

Overly Excessive


1 Answers

Here is an naive implementation of the sequence Gustavo talked about:

let rec sequence = 
   function 
   | [] -> Some [] 
   | (Some o :: os) -> 
      sequence os 
      |> Option.map (fun os' -> o::os') 
   | _ -> None

(please note that this is not tail-recursive and not optimized at all so you should transform it if you gonna need it for large lists)

Which would work just as Gustavo told you:

> sequence [Some 1; Some 2; Some 2] |> Option.map List.sum;;
val it : int option = Some 5

> sequence [Some 1; None; Some 2] |> Option.map List.sum;;
val it : int option = None    
like image 158
Random Dev Avatar answered Nov 07 '22 23:11

Random Dev