Skip to content

Instantly share code, notes, and snippets.

@AlexCuse
Created June 7, 2011 16:51
Show Gist options
  • Save AlexCuse/1012647 to your computer and use it in GitHub Desktop.
Save AlexCuse/1012647 to your computer and use it in GitHub Desktop.
Seq option merge
#light
open System
module Seq =
let merge (s1:seq<option<'a>>) (s2:seq<option<'a>>) =
let rec innerMerge s1 s2 =
seq {
match s1, s2 with
| LazyList.Cons(h1, t1), LazyList.Cons(h2, t2) ->
yield h1
yield h2
yield! innerMerge t1 t2
| LazyList.Cons(h1, t1), LazyList.Nil ->
yield h1
yield! innerMerge t1 s2
| LazyList.Nil, LazyList.Cons(h2, t2) ->
yield h2
yield! innerMerge s1 t2
| LazyList.Nil, LazyList.Nil ->
yield! innerMerge s1 s2
}
innerMerge (LazyList.ofSeq s1) (LazyList.ofSeq s2)
let excludeEmptyOptions (s:seq<option<'a>>) =
s |> Seq.filter (fun opt ->
match opt with
| Some o -> true
| None -> false)
|> Seq.map (fun opt ->
match opt with
| Some o -> o
| None -> failwith "wtf")
let ms() = DateTime.Now.Millisecond
let first =
seq {
while true do
if ms() % 50 = 0 then yield Some "fifty"
else yield None
}
let second =
seq {
while true do
//for normal merge this won't work (need string) - this is here to test w/ heterogenous type when mapping to async
if ms() % 10 = 0 then yield Some 10
else yield None
}
let write v formatstring =
match v with
| Some a -> Some(async { printfn formatstring a })
| None -> None
//first |> Seq.merge second |> Seq.excludeEmpty |> Seq.take 100 |> Seq.iter (fun s -> printfn "%s" s)
(first |> Seq.map (fun v -> write v "%s"))
|> Seq.merge (second |> Seq.map (fun v -> write v "%d"))
|> Seq.excludeEmptyOptions
|> Seq.take 100
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment