Advertisement
Guest User

Untitled

a guest
Oct 22nd, 2010
239
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.37 KB | None | 0 0
  1. open System.Collections
  2. open System.Collections.Generic
  3.  
  4. // ----------------------------------------------------------------------------
  5. // Module with basic functions for working with IEnumerator<'a>
  6.  
  7. module Enumerator =
  8. let single a =
  9. let state = ref 0
  10. { new IEnumerator<_> with
  11. member self.Current = if (state.Value = 1) then a else invalidOp "!"
  12. interface System.Collections.IEnumerator with
  13. member self.Current = if (state.Value = 1) then box a else invalidOp "!"
  14. member self.MoveNext() = state := state.Value + 1; state.Value = 1
  15. member self.Reset() = state := 0
  16. interface System.IDisposable with
  17. member self.Dispose() = ()}
  18.  
  19. let combine (a:IEnumerator<_>) b =
  20. let current = ref a
  21. let first = ref true
  22. { new IEnumerator<_> with
  23. member self.Current = current.Value.Current
  24. interface System.Collections.IEnumerator with
  25. member self.Current = box current.Value.Current
  26. member self.MoveNext() =
  27. if current.Value.MoveNext() then true
  28. elif first.Value then
  29. current := b
  30. first := false
  31. current.Value.MoveNext()
  32. else false
  33. member self.Reset() =
  34. a.Reset(); b.Reset()
  35. first := true; current := a
  36. interface System.IDisposable with
  37. member self.Dispose() = a.Dispose(); b.Dispose() }
  38.  
  39. let zero () =
  40. { new IEnumerator<_> with
  41. member self.Current = invalidOp "!"
  42. interface System.Collections.IEnumerator with
  43. member self.Current = invalidOp "!"
  44. member self.MoveNext() = false
  45. member self.Reset() = ()
  46. interface System.IDisposable with
  47. member self.Dispose() = ()}
  48.  
  49. let delay f =
  50. let en : Lazy<IEnumerator<_>> = lazy f()
  51. { new IEnumerator<_> with
  52. member self.Current = en.Value.Current
  53. interface System.Collections.IEnumerator with
  54. member self.Current = box en.Value.Current
  55. member self.MoveNext() = en.Value.MoveNext()
  56. member self.Reset() = en.Value.Reset()
  57. interface System.IDisposable with
  58. member self.Dispose() = en.Value.Dispose() }
  59.  
  60. let toSeq gen =
  61. { new IEnumerable<'T> with
  62. member x.GetEnumerator() = gen()
  63. interface IEnumerable with
  64. member x.GetEnumerator() = (gen() :> IEnumerator) }
  65.  
  66. // ----------------------------------------------------------------------------
  67. // Computation builder for working with enumerators
  68.  
  69. type EnumerableBuilder() =
  70. member x.Delay(f) = Enumerator.delay f
  71. member x.YieldFrom(a) = a
  72. member x.Yield(a) = Enumerator.single a
  73. member x.Bind(a:IEnumerator<'a>, f:_ -> IEnumerator<'b>) =
  74. if (a.MoveNext()) then f (Some(a.Current)) else f(None)
  75. member x.Combine(a, b) = Enumerator.combine a b
  76. member x.Zero() = Enumerator.zero ()
  77.  
  78. let iter = new EnumerableBuilder()
  79.  
  80. // Enumerator that produces 3 numbers
  81. let e = iter { yield 1; yield 2; yield 3 }
  82. e.MoveNext()
  83. e.Current
  84.  
  85. // Enumerator that iumplements "identity" and prints elements
  86. let rec loop e = iter {
  87. let! v = e
  88. printfn "%A" v
  89. yield v
  90. yield! loop e }
  91.  
  92. let e2 = iter { yield 1; yield 2; yield 3 }
  93. let r = loop e2
  94.  
  95. r.MoveNext()
  96. r.Current
  97.  
  98. // Implementing the zip function for enumerators
  99. let rec zipE xs ys = iter {
  100. let! x = xs
  101. let! y = ys
  102. match x, y with
  103. | Some(x), Some(y) ->
  104. yield x, y
  105. yield! zipE xs ys
  106. | _ -> () }
  107.  
  108. // Implementing zip for sequences using zip for enumerators
  109. let zip (a:seq<_>) (b:seq<_>) =
  110. Enumerator.toSeq (fun () ->
  111. zipE (a.GetEnumerator()) (b.GetEnumerator()))
  112.  
  113. zip [1;2;3] ["a";"b";"c"]
  114. zip [1;2;3;4] ["a";"b";"c"]
  115.  
  116. let rec map f en = iter {
  117. let! x = en
  118. match x with
  119. | Some(x) -> yield f x
  120. yield! map f en
  121. | _ -> () }
  122.  
  123. // Implementing zip for sequences using zip for enumerators
  124. let zipWithFun f g h (a:seq<_>) (b:seq<_>) =
  125. let rec zipWithFunE xs ys = iter {
  126. let! x = xs
  127. let! y = ys
  128. match x, y with
  129. | Some(x), Some(y) ->
  130. yield f (x, y)
  131. yield! zipWithFunE xs ys
  132. | Some(rest), _ ->
  133. yield g rest
  134. yield! xs |> map g
  135. | _, Some(rest) ->
  136. yield h rest
  137. yield! ys |> map h
  138. | _ -> () }
  139.  
  140. Enumerator.toSeq (fun () ->
  141. zipE (a.GetEnumerator()) (b.GetEnumerator()))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement