Enumerator computation builder

The snippet defines computation builder for working with IEnumerator. The bind operation (let!) reads next element from the enumerator, so the computation can be used for expressing things that cannot be written just using seq.

Copy Source
Copy Link
Tools:

Module with basic functions for working with IEnumerator

 1: module Enumerator = 
 2: 
 3:   let single a = 
 4:     let state = ref 0
 5:     { new IEnumerator<_> with 
 6:         member self.Current = if (state.Value = 1) then a else invalidOp "!"
 7:       interface System.Collections.IEnumerator with
 8:         member self.Current = if (state.Value = 1) then box a else invalidOp "!"
 9:         member self.MoveNext() = state := state.Value + 1; state.Value = 1
10:         member self.Reset() = state := 0
11:       interface System.IDisposable with 
12:         member self.Dispose() = ()}
13: 
14:   let combine (a:IEnumerator<_>) b = 
15:     let current = ref a
16:     let first = ref true
17:     { new IEnumerator<_> with 
18:         member self.Current = current.Value.Current
19:       interface System.Collections.IEnumerator with
20:         member self.Current = box current.Value.Current
21:         member self.MoveNext() = 
22:           if current.Value.MoveNext() then true 
23:           elif first.Value then 
24:             current := b
25:             first := false
26:             current.Value.MoveNext()
27:           else false
28:         member self.Reset() = 
29:           a.Reset(); b.Reset()
30:           first := true; current := a
31:       interface System.IDisposable with 
32:         member self.Dispose() = a.Dispose(); b.Dispose() }
33:   
34:   let zero () = 
35:     { new IEnumerator<_> with 
36:         member self.Current = invalidOp "!"
37:       interface System.Collections.IEnumerator with
38:         member self.Current = invalidOp "!"
39:         member self.MoveNext() = false
40:         member self.Reset() = ()
41:       interface System.IDisposable with 
42:         member self.Dispose() = ()}
43:   
44:   let delay f = 
45:     let en : Lazy<IEnumerator<_>> = lazy f()
46:     { new IEnumerator<_> with 
47:         member self.Current = en.Value.Current
48:       interface System.Collections.IEnumerator with
49:         member self.Current = box en.Value.Current
50:         member self.MoveNext() = en.Value.MoveNext()
51:         member self.Reset() = en.Value.Reset()
52:       interface System.IDisposable with 
53:         member self.Dispose() = en.Value.Dispose() }
54: 
55:   let toSeq gen = 
56:     { new IEnumerable<'T> with 
57:           member x.GetEnumerator() = gen() 
58:       interface IEnumerable with 
59:           member x.GetEnumerator() = (gen() :> IEnumerator) }

Computation builder for working with enumerators

 1: type EnumerableBuilder() = 
 2:   member x.Delay(f) = Enumerator.delay f
 3:   member x.YieldFrom(a) = a
 4:   member x.Yield(a) = Enumerator.single a
 5:   member x.Bind(a:IEnumerator<'a>, f:_ -> IEnumerator<'b>) =
 6:     if (a.MoveNext()) then f (Some(a.Current)) else f(None) 
 7:   member x.Combine(a, b) = Enumerator.combine a b
 8:   member x.Zero() = Enumerator.zero ()
 9: 
10: let iter = new EnumerableBuilder()    

Examples of using 'iter' computations

 1: // Enumerator that produces 3 numbers
 2: let e = iter { yield 1; yield 2; yield 3 }
 3: e.MoveNext()
 4: e.Current
 5: 
 6: // Enumerator that iumplements "identity" and prints elements
 7: let rec loop e = iter {
 8:   let! v = e
 9:   printfn "%A" v
10:   yield v
11:   yield! loop e }
12:   
13: let e2 = iter { yield 1; yield 2; yield 3 }
14: let r = loop e2
15: 
16: r.MoveNext()
17: r.Current
18: 
19: // Implementing the zip function for enumerators
20: let rec zipE xs ys = iter {
21:   let! x = xs
22:   let! y = ys
23:   match x, y with 
24:   | Some(x), Some(y) ->
25:     yield x, y
26:     yield! zipE xs ys 
27:   | _ -> () }
28: 
29: // Implementing zip for sequences using zip for enumerators
30: let zip (a:seq<_>) (b:seq<_>) = 
31:   Enumerator.toSeq (fun () -> 
32:     zipE (a.GetEnumerator()) (b.GetEnumerator()))
33: 
34: zip [1;2;3] ["a";"b";"c"]
35: zip [1;2;3;4] ["a";"b";"c"]
Multiple items
val single : 'a -> IEnumerator<'a>

Full name: Snippet.Enumerator.single

--------------------

type single = System.Single

Full name: Microsoft.FSharp.Core.single

  type: single
  implements: System.IComparable
  implements: System.IFormattable
  implements: System.IConvertible
  implements: System.IComparable<float32>
  implements: System.IEquatable<float32>
  inherits: System.ValueType
val a : 'a
val state : int ref

  type: int ref
  implements: IStructuralEquatable
  implements: System.IComparable<Ref<int>>
  implements: System.IComparable
  implements: IStructuralComparable
Multiple items
val ref : 'T -> 'T ref

Full name: Microsoft.FSharp.Core.Operators.ref

--------------------

type 'T ref = Ref<'T>

Full name: Microsoft.FSharp.Core.ref<_>

  type: 'T ref
  implements: IStructuralEquatable
  implements: System.IComparable<Ref<'T>>
  implements: System.IComparable
  implements: IStructuralComparable
Multiple items
type IEnumerator<'T> =
  interface
    member Current : 'T
  end

Full name: System.Collections.Generic.IEnumerator<_>

  type: IEnumerator<'T>
  inherits: System.IDisposable
  inherits: IEnumerator


--------------------

type IEnumerator =
  interface
    member Current : obj
    member MoveNext : unit -> bool
    member Reset : unit -> unit
  end

Full name: System.Collections.IEnumerator

--------------------

IEnumerator

--------------------

IEnumerator
val self : IEnumerator<'a>

  type: IEnumerator<'a>
  inherits: System.IDisposable
  inherits: IEnumerator
property IEnumerator.Current: 'a
property Ref.Value: int
val invalidOp : string -> 'T

Full name: Microsoft.FSharp.Core.Operators.invalidOp
namespace System
namespace System.Collections
Multiple items
type IEnumerator =
  interface
    member Current : obj
    member MoveNext : unit -> bool
    member Reset : unit -> unit
  end

Full name: System.Collections.IEnumerator

--------------------

IEnumerator
val self : IEnumerator
property IEnumerator.Current: obj
val box : 'T -> obj

Full name: Microsoft.FSharp.Core.Operators.box
IEnumerator.MoveNext() : bool
IEnumerator.Reset() : unit
Multiple items
type IDisposable =
  interface
    member Dispose : unit -> unit
  end

Full name: System.IDisposable

--------------------

System.IDisposable
val self : System.IDisposable
System.IDisposable.Dispose() : unit
val combine : IEnumerator<'a> -> IEnumerator<'a> -> IEnumerator<'a>

Full name: Snippet.Enumerator.combine
val a : IEnumerator<'a>

  type: IEnumerator<'a>
  inherits: System.IDisposable
  inherits: IEnumerator
val b : IEnumerator<'a>

  type: IEnumerator<'a>
  inherits: System.IDisposable
  inherits: IEnumerator
val current : IEnumerator<'a> ref

  type: IEnumerator<'a> ref
  implements: IStructuralEquatable
  implements: System.IComparable<Ref<IEnumerator<'a>>>
  implements: System.IComparable
  implements: IStructuralComparable
val first : bool ref

  type: bool ref
  implements: IStructuralEquatable
  implements: System.IComparable<Ref<bool>>
  implements: System.IComparable
  implements: IStructuralComparable
property Ref.Value: IEnumerator<'a>
property Ref.Value: bool
val zero : unit -> IEnumerator<'a>

Full name: Snippet.Enumerator.zero
val delay : (unit -> IEnumerator<'a>) -> IEnumerator<'a>

Full name: Snippet.Enumerator.delay
val f : (unit -> IEnumerator<'a>)
val en : Lazy<IEnumerator<'a>>
Multiple items
active recognizer Lazy: Lazy<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.( |Lazy| )

--------------------

type Lazy<'T> = System.Lazy<'T>

Full name: Microsoft.FSharp.Control.Lazy<_>
property System.Lazy.Value: IEnumerator<'a>
val toSeq : (unit -> IEnumerator<'T>) -> IEnumerable<'T>

Full name: Snippet.Enumerator.toSeq
val gen : (unit -> IEnumerator<'T>)
Multiple items
type IEnumerable<'T> =
  interface
    member GetEnumerator : unit -> System.Collections.Generic.IEnumerator<'T>
  end

Full name: System.Collections.Generic.IEnumerable<_>

  type: IEnumerable<'T>
  inherits: IEnumerable


--------------------

type IEnumerable =
  interface
    member GetEnumerator : unit -> System.Collections.IEnumerator
  end

Full name: System.Collections.IEnumerable

--------------------

IEnumerable

--------------------

IEnumerable
val x : IEnumerable<'T>

  type: IEnumerable<'T>
  inherits: IEnumerable
IEnumerable.GetEnumerator() : IEnumerator<'T>
val x : IEnumerable
IEnumerable.GetEnumerator() : IEnumerator
type EnumerableBuilder =
  class
    new : unit -> EnumerableBuilder
    member Bind : a:IEnumerator<'a> * f:('a option -> IEnumerator<'b>) -> IEnumerator<'b>
    member Combine : a:IEnumerator<'b> * b:IEnumerator<'b> -> IEnumerator<'b>
    member Delay : f:(unit -> IEnumerator<'e>) -> IEnumerator<'e>
    member Yield : a:'c -> IEnumerator<'c>
    member YieldFrom : a:'d -> 'd
    member Zero : unit -> IEnumerator<'a>
  end

Full name: Snippet.EnumerableBuilder
val x : EnumerableBuilder
member EnumerableBuilder.Delay : f:(unit -> IEnumerator<'e>) -> IEnumerator<'e>

Full name: Snippet.EnumerableBuilder.Delay
val f : (unit -> IEnumerator<'e>)
module Enumerator

from Snippet
member EnumerableBuilder.YieldFrom : a:'d -> 'd

Full name: Snippet.EnumerableBuilder.YieldFrom
val a : 'd
member EnumerableBuilder.Yield : a:'c -> IEnumerator<'c>

Full name: Snippet.EnumerableBuilder.Yield
val a : 'c
val single : 'a -> IEnumerator<'a>

Full name: Snippet.Enumerator.single
member EnumerableBuilder.Bind : a:IEnumerator<'a> * f:('a option -> IEnumerator<'b>) -> IEnumerator<'b>

Full name: Snippet.EnumerableBuilder.Bind
val f : ('a option -> IEnumerator<'b>)
union case Option.Some: 'T -> Option<'T>
union case Option.None: Option<'T>
member EnumerableBuilder.Combine : a:IEnumerator<'b> * b:IEnumerator<'b> -> IEnumerator<'b>

Full name: Snippet.EnumerableBuilder.Combine
val a : IEnumerator<'b>

  type: IEnumerator<'b>
  inherits: System.IDisposable
  inherits: IEnumerator
val b : IEnumerator<'b>

  type: IEnumerator<'b>
  inherits: System.IDisposable
  inherits: IEnumerator
member EnumerableBuilder.Zero : unit -> IEnumerator<'a>

Full name: Snippet.EnumerableBuilder.Zero
val iter : EnumerableBuilder

Full name: Snippet.iter
val e : IEnumerator<int>

Full name: Snippet.e

  type: IEnumerator<int>
  inherits: System.IDisposable
  inherits: IEnumerator
property IEnumerator.Current: int
val loop : IEnumerator<'a> -> IEnumerator<'a option>

Full name: Snippet.loop
val e : IEnumerator<'a>

  type: IEnumerator<'a>
  inherits: System.IDisposable
  inherits: IEnumerator
val v : 'a option

  type: 'a option
  implements: IStructuralEquatable
  implements: System.IComparable<Option<'a>>
  implements: System.IComparable
  implements: IStructuralComparable
val printfn : Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val e2 : IEnumerator<int>

Full name: Snippet.e2

  type: IEnumerator<int>
  inherits: System.IDisposable
  inherits: IEnumerator
val r : IEnumerator<int option>

Full name: Snippet.r

  type: IEnumerator<int option>
  inherits: System.IDisposable
  inherits: IEnumerator
property IEnumerator.Current: int option
val zipE : IEnumerator<'a> -> IEnumerator<'b> -> IEnumerator<'a * 'b>

Full name: Snippet.zipE
val xs : IEnumerator<'a>

  type: IEnumerator<'a>
  inherits: System.IDisposable
  inherits: IEnumerator
val ys : IEnumerator<'b>

  type: IEnumerator<'b>
  inherits: System.IDisposable
  inherits: IEnumerator
val x : 'a option

  type: 'a option
  implements: IStructuralEquatable
  implements: System.IComparable<Option<'a>>
  implements: System.IComparable
  implements: IStructuralComparable
val y : 'b option

  type: 'b option
  implements: IStructuralEquatable
  implements: System.IComparable<Option<'b>>
  implements: System.IComparable
  implements: IStructuralComparable
val x : 'a
val y : 'b
val zip : seq<'a> -> seq<'b> -> IEnumerable<'a * 'b>

Full name: Snippet.zip
val a : seq<'a>

  type: seq<'a>
  inherits: IEnumerable
Multiple items
val seq : seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------

type seq<'T> = IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>

  type: seq<'T>
  inherits: IEnumerable
val b : seq<'b>

  type: seq<'b>
  inherits: IEnumerable
IEnumerable.GetEnumerator() : IEnumerator<'a>
IEnumerable.GetEnumerator() : IEnumerator<'b>

More information

Link: http://fssnip.net/37
Posted: 3 years ago
Author: Tomas Petricek (website)
Tags: enumerator, seq, ienumerator, computation builder