package lazy type ( // Lazy represents a synchronous computation without side effects. // It is a function that takes no arguments and returns a value of type A. // // Lazy computations are evaluated only when their result is needed (lazy evaluation). // This allows for: // - Deferring expensive computations until they're actually required // - Creating infinite data structures // - Implementing memoization patterns // - Composing pure computations in a functional style // // Example: // // // Create a lazy computation // computation := lazy.Of(42) // // // Transform it (not evaluated yet) // doubled := lazy.Map(N.Mul(2))(computation) // // // Evaluate when needed // result := doubled() // 84 // // Note: Lazy is an alias for io.IO[A] but represents pure computations // without side effects, whereas IO represents computations that may have side effects. Lazy[A any] = func() A // Kleisli represents a function that takes a value of type A and returns // a lazy computation producing a value of type B. // // Kleisli arrows are used for composing monadic computations. They allow // you to chain operations where each step depends on the result of the previous step. // // Example: // // // A Kleisli arrow that doubles a number lazily // double := func(x int) lazy.Lazy[int] { // return lazy.Of(x * 2) // } // // // Chain it with another operation // result := lazy.Chain(double)(lazy.Of(5))() // 10 Kleisli[A, B any] = func(A) Lazy[B] // Operator represents a function that takes a lazy computation of type A // and returns a lazy computation of type B. // // Operators are used to transform lazy computations. They are essentially // Kleisli arrows where the input is already wrapped in a Lazy context. // // Example: // // // An operator that doubles the value in a lazy computation // doubleOp := lazy.Map(N.Mul(2)) // // // Apply it to a lazy computation // result := doubleOp(lazy.Of(5))() // 10 Operator[A, B any] = Kleisli[Lazy[A], B] )