Skip to content

Instantly share code, notes, and snippets.

@mrange
Created August 2, 2016 06:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrange/18e3b3a755f8fa180f1975ae76f1f616 to your computer and use it in GitHub Desktop.
Save mrange/18e3b3a755f8fa180f1975ae76f1f616 to your computer and use it in GitHub Desktop.
module PushPipe =
type Finalizer<'T> = unit -> 'T
type Receiver<'T> = 'T -> bool
type Pipe<'T, 'I> = Receiver<'T> -> Receiver<'I>
type Sink<'T, 'I> = Receiver<'I>*Finalizer<'T>
let inline debug (name : string) (p : Pipe<'T, 'I>) : Pipe<'T, 'I> =
fun r -> p (fun v -> printfn "PIPE: %s - %A" name v; r v)
let inline filter (f : 'T -> bool) (p : Pipe<'T, 'I>) : Pipe<'T, 'I> =
fun r -> p (fun v -> if f v then r v else true)
let inline map (m : 'T -> 'U) (p : Pipe<'T, 'I>) : Pipe<'U, 'I> =
fun r -> p (fun v -> r (m v))
let inline mapi (m : int -> 'T -> 'U) (p : Pipe<'T, 'I>) : Pipe<'U, 'I> =
let om = OptimizedClosures.FSharpFunc<_, _, _>.Adapt m
fun r ->
let mutable i = -1
p (fun v -> i <- i + 1; r (m i v))
let fromArray : Pipe<'T, 'T []> =
fun r vs ->
let rec loop i = if i <= vs.Length && r vs.[i] then loop (i + 1) else true
loop 0
let passThrough<'T> : Pipe<'T, 'T> =
fun r v -> r v
let range : Pipe<int, int*int*int> =
fun r (b, s, e) ->
let rec loop i = if i <= e && r i then loop (i + s) else true
loop b
let inline toArray (p : Pipe<'T, 'I>) : Sink<'T [], 'I> =
let ra = ResizeArray<'T> 16
let r v = ra.Add v; true
let f () = ra.ToArray ()
p r, f
let inline sum (p : Pipe<'T, 'I>) : Sink<'T, 'I> =
let s = ref LanguagePrimitives.GenericZero
let r v = s := !s + v; true
let f () = !s
p r, f
let doIt () =
let r, f =
range
|> map ((+) 1)
|> filter (fun v -> v % 2 = 0)
|> sum
r (0, 1, 1000) |> ignore
printfn "%A" (f ())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment