// [snippet:Using declared functions]
let range = [0..999]
let condition x = x % 3 = 0 || x % 5 = 0

range 
  |> List.filter condition 
  |> List.fold (+) 0
// [/snippet]
// [snippet: Using lambda functions]
[0..999] 
  |> Seq.filter (fun x -> x % 3 = 0 || x % 5 = 0) 
  |> Seq.reduce (+)
// [/snippet]
// [snippet: Using sequence expressions]
seq { for x in 0 .. 999 do
      if x % 3 = 0 || x % 5 = 0 then yield x }
|> Seq.sum
// [/snippet]
// [snippet: Using recursive function for ultimate speed]
let rec multiple x =
  if x = 1000 then 0
  elif x%3 = 0 || x%5 = 0 then x + multiple (x+1)
  else multiple (x+1)
  
multiple 1
// [/snippet]
// [snippet: Using accumulator for tail-recursive and pattern matching]
let rec mul' acc x =
  match x with
  | 999L -> acc + x 
  | x when (x%3L=0L||x%5L=0L) ->       
      mul' (acc + x) (x + 1L)   
  | _ -> 
      mul' acc (x + 1L)

mul' 0L 1L
// [/snippet]
//[snippet: Fast calculation (generalized solution)]
let mSum (multipliers:int list) limit =
//if 1 + 2 + .. + n = n*(n+1)/2
  let aSum n = n*(n+1I) >>> 1

//then k + 2k + .. + k*n = k*(aSum n), where n = limit/k
  let lSum limit k = limit/k |> aSum |> (*) k

//make all combinations of multipliers
//thanks to Alexander Rautenberg
  let allCombinations lst =
     let rec comb accLst elemLst =
         match elemLst with
         | h::t ->
             let next = [h]::List.map (fun el -> h::el) accLst @ accLst
             comb next t
         | _ -> accLst
     comb [] lst

//and do calculations using inclusion–exclusion principle
  multipliers 
   |> allCombinations 
   |> List.map  (fun l -> let k = List.reduce (*) l |> bigint in
                           if (List.length l) % 2 = 0 then 
                             -(lSum limit k)
                           else 
                              lSum limit k
                )
   |> List.sum

let ans = mSum [3;  5] 999I
//[/snippet]