11 people like it.

LazyBuilder

I made LazyBuilder. The synthesis of the lazy function is troublesome. When the call of the Force() method increases, it is ugly. This solves the problem.

LazyBuilder

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
module Lazy =

  type LazyBuilder () =
    let force (x : Lazy<'T>) = x |> function | Lazy x -> x
    /// bind
    let (>>=) (x:Lazy<'a>) (f:('a -> Lazy<'a>)) : Lazy<'a> =
      lazy (x |> force |> f |> force)  
    /// zero
    let lazyzero = Seq.empty
    
    member this.Bind(x, f) = x >>= f
    member this.Return (x) = lazy x
    member this.ReturnFrom (x) = x
    member this.Zero() = lazyzero 
    member this.Delay f = f()

    member this.Combine (a,b) = 
      Seq.append a b 

    member this.Combine (a,b) = 
      Seq.append (Seq.singleton a) b

    member this.Combine (a,b) = 
      Seq.append a (Seq.singleton b) 

    member this.Combine (Lazy(a), Lazy(b)) = 
      lazy Seq.append a b 

    member this.Combine (a:Lazy<'T>, b:Lazy<seq<'T>>) = 
      (a,b) |> function | (Lazy x, Lazy y) -> lazy Seq.append (Seq.singleton x) y

    member this.Combine (a:Lazy<seq<'T>>, Lazy(b)) = 
      a |> function | Lazy x -> lazy Seq.append x (Seq.singleton b) 

    member this.Combine (a:Lazy<seq<'T>>, b:seq<Lazy<'T>>) =
      let notlazy (xs:seq<Lazy<'T>>) = xs |> Seq.map (fun (Lazy(a)) -> a)
      a |> function | Lazy x -> lazy Seq.append x (notlazy b) 

    member this.Combine (a:seq<Lazy<'T>>, b:Lazy<seq<'T>>) =
      let notlazy (xs:seq<Lazy<'T>>) = xs |> Seq.map (fun (Lazy(a)) -> a)
      b |> function | Lazy x -> lazy Seq.append (notlazy a) x  

    member this.For (s,f) =
      s |> Seq.map f 

    member this.Yield x = lazy x
    member this.YieldFrom x = x

    member this.Run (x:Lazy<'T>) = x
    member this.Run (xs:seq<Lazy<unit>>) = 
      xs |> Seq.reduce (fun a b -> this.Bind(a, fun _ -> b)) 
    member this.Run (xs:seq<Lazy<'T>>) = 
      xs |> Seq.map (fun (Lazy(a)) -> a) |> fun x -> lazy x

  let lazyz = LazyBuilder () 
  let lifM f (Lazy(a)) = lazy f a   

Sample

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
open System
open Lazy
let result = 
  lazyz { let! a = lazy ("Hello,")
          let! b = lazy ("World!")
          return a + b}
result.Force() |> (printfn "%s") |> ignore

let lazyp n = lazy (printfn "%d" n)
let result2 = 
  let a = 
    lazyz {
        yield! lazyp 2
        ()}

  lazyz {
    yield! lazyp 0
    yield! lazyp 1
    yield! a
    for i in 3..5 do
      yield! lazyp i 
    yield! lazyp 6
    yield! lazyz {
              yield! lazyp 7
              yield! lazyp 8
              ()}
    for i in 9..10 do
      yield! lazyp i 
    yield! seq {for n in [11..15] -> lazyp n}
    yield! lazyz {
              yield! lazyp 16
              yield! lazyp 17
              ()}
    yield! lazyz {
              yield! lazyp 18
              yield! lazyp 19
              ()}
    yield! lazyp 20
    ()  }
result2.Force() 
Console.ReadLine () |> ignore
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<_>
Multiple items
type LazyBuilder =
  new : unit -> LazyBuilder
  member Bind : x:Lazy<'o> * f:('o -> Lazy<'o>) -> Lazy<'o>
  member Combine : a:seq<'j> * b:seq<'j> -> seq<'j>
  member Combine : a:'i * b:seq<'i> -> seq<'i>
  member Combine : a:seq<'h> * b:'h -> seq<'h>
  member Combine : Lazy<#seq<'f>> * Lazy<#seq<'f>> -> Lazy<seq<'f>>
  member Combine : a:Lazy<'T> * b:Lazy<seq<'T>> -> Lazy<seq<'T>>
  member Combine : a:Lazy<seq<'T>> * Lazy<'T> -> Lazy<seq<'T>>
  member Combine : a:Lazy<seq<'T>> * b:seq<Lazy<'T>> -> Lazy<seq<'T>>
  member Combine : a:seq<Lazy<'T>> * b:Lazy<seq<'T>> -> Lazy<seq<'T>>
  ...

Full name: Script.Lazy.LazyBuilder

--------------------
new : unit -> LazyBuilder
val force : (Lazy<'T> -> 'T)
val x : Lazy<'T>
val x : 'T
val x : Lazy<'a>
val f : ('a -> Lazy<'a>)
val lazyzero : seq<'a>


 zero
module Seq

from Microsoft.FSharp.Collections
val empty<'T> : seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.empty
val this : LazyBuilder
member LazyBuilder.Bind : x:Lazy<'o> * f:('o -> Lazy<'o>) -> Lazy<'o>

Full name: Script.Lazy.LazyBuilder.Bind
val x : Lazy<'o>
val f : ('o -> Lazy<'o>)
member LazyBuilder.Return : x:'n -> Lazy<'n>

Full name: Script.Lazy.LazyBuilder.Return
val x : 'n
member LazyBuilder.ReturnFrom : x:'m -> 'm

Full name: Script.Lazy.LazyBuilder.ReturnFrom
val x : 'm
member LazyBuilder.Zero : unit -> seq<'l>

Full name: Script.Lazy.LazyBuilder.Zero
member LazyBuilder.Delay : f:(unit -> 'k) -> 'k

Full name: Script.Lazy.LazyBuilder.Delay
val f : (unit -> 'k)
member LazyBuilder.Combine : a:seq<'j> * b:seq<'j> -> seq<'j>

Full name: Script.Lazy.LazyBuilder.Combine
val a : seq<'j>
val b : seq<'j>
val append : source1:seq<'T> -> source2:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.append
member LazyBuilder.Combine : a:'i * b:seq<'i> -> seq<'i>

Full name: Script.Lazy.LazyBuilder.Combine
val a : 'i
val b : seq<'i>
val singleton : value:'T -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.singleton
member LazyBuilder.Combine : a:seq<'h> * b:'h -> seq<'h>

Full name: Script.Lazy.LazyBuilder.Combine
val a : seq<'h>
val b : 'h
member LazyBuilder.Combine : Lazy<#seq<'f>> * Lazy<#seq<'f>> -> Lazy<seq<'f>>

Full name: Script.Lazy.LazyBuilder.Combine
val a : #seq<'f>
val b : #seq<'f>
member LazyBuilder.Combine : a:Lazy<'T> * b:Lazy<seq<'T>> -> Lazy<seq<'T>>

Full name: Script.Lazy.LazyBuilder.Combine
val a : Lazy<'T>
val b : Lazy<seq<'T>>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

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

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val y : seq<'T>
member LazyBuilder.Combine : a:Lazy<seq<'T>> * Lazy<'T> -> Lazy<seq<'T>>

Full name: Script.Lazy.LazyBuilder.Combine
val a : Lazy<seq<'T>>
val b : 'T
val x : seq<'T>
member LazyBuilder.Combine : a:Lazy<seq<'T>> * b:seq<Lazy<'T>> -> Lazy<seq<'T>>

Full name: Script.Lazy.LazyBuilder.Combine
val b : seq<Lazy<'T>>
val notlazy : (seq<Lazy<'T>> -> seq<'T>)
val xs : seq<Lazy<'T>>
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map
val a : 'T
member LazyBuilder.Combine : a:seq<Lazy<'T>> * b:Lazy<seq<'T>> -> Lazy<seq<'T>>

Full name: Script.Lazy.LazyBuilder.Combine
val a : seq<Lazy<'T>>
member LazyBuilder.For : s:seq<'c> * f:('c -> 'd) -> seq<'d>

Full name: Script.Lazy.LazyBuilder.For
val s : seq<'c>
val f : ('c -> 'd)
member LazyBuilder.Yield : x:'b -> Lazy<'b>

Full name: Script.Lazy.LazyBuilder.Yield
val x : 'b
member LazyBuilder.YieldFrom : x:'a -> 'a

Full name: Script.Lazy.LazyBuilder.YieldFrom
val x : 'a
member LazyBuilder.Run : x:Lazy<'T> -> Lazy<'T>

Full name: Script.Lazy.LazyBuilder.Run
member LazyBuilder.Run : xs:seq<Lazy<unit>> -> Lazy<unit>

Full name: Script.Lazy.LazyBuilder.Run
val xs : seq<Lazy<unit>>
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
val reduce : reduction:('T -> 'T -> 'T) -> source:seq<'T> -> 'T

Full name: Microsoft.FSharp.Collections.Seq.reduce
val a : Lazy<unit>
val b : Lazy<unit>
member LazyBuilder.Bind : x:Lazy<'o> * f:('o -> Lazy<'o>) -> Lazy<'o>
member LazyBuilder.Run : xs:seq<Lazy<'T>> -> Lazy<seq<'T>>

Full name: Script.Lazy.LazyBuilder.Run
val lazyz : LazyBuilder

Full name: Script.Lazy.lazyz
val lifM : f:('a -> 'b) -> Lazy<'a> -> Lazy<'b>

Full name: Script.Lazy.lifM
val f : ('a -> 'b)
val a : 'a
namespace System
Multiple items
active recognizer Lazy: Lazy<'T> -> 'T

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

--------------------
type Lazy<'T> =
  new : unit -> Lazy<'T> + 5 overloads
  member IsValueCreated : bool
  member ToString : unit -> string
  member Value : 'T

Full name: System.Lazy<_>

--------------------
Lazy() : unit
Lazy(valueFactory: Func<'T>) : unit
Lazy(isThreadSafe: bool) : unit
Lazy(mode: Threading.LazyThreadSafetyMode) : unit
Lazy(valueFactory: Func<'T>, isThreadSafe: bool) : unit
Lazy(valueFactory: Func<'T>, mode: Threading.LazyThreadSafetyMode) : unit
val result : Lazy<string>

Full name: Script.result
val a : string
val b : string
member Lazy.Force : unit -> 'T
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val lazyp : n:int -> Lazy<unit>

Full name: Script.lazyp
val n : int
val result2 : Lazy<unit>

Full name: Script.result2
val i : int
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

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

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
type Console =
  static member BackgroundColor : ConsoleColor with get, set
  static member Beep : unit -> unit + 1 overload
  static member BufferHeight : int with get, set
  static member BufferWidth : int with get, set
  static member CapsLock : bool
  static member Clear : unit -> unit
  static member CursorLeft : int with get, set
  static member CursorSize : int with get, set
  static member CursorTop : int with get, set
  static member CursorVisible : bool with get, set
  ...

Full name: System.Console
Console.ReadLine() : string
Raw view New version

More information

Link:http://fssnip.net/67
Posted:5 years ago
Author:zecl
Tags: lazy , computation builder , monad